【发布时间】:2015-07-20 19:56:57
【问题描述】:
我们有一个多租户数据库,其中包含多个客户,每个客户都有一个这样的用户集合(省略从用户到客户的外键规范的简化示例):
CREATE TABLE dbo.Customers
(
CustomerId INT NOT NULL IDENTITY(1, 1),
Name NVARCHAR(256) NOT NULL
)
CREATE TABLE dbo.Users
(
User INT NOT NULL IDENTITY(1, 1),
CustomerId INT NOT NULL,
)
作为此设计的一部分,用户需要有一个会员编号,当我们设计这个时,我们决定使用 UserId 作为会员编号,但是随着所有事情的发展,这个要求已经增长,这不再是两个人的选择原因:
在每次服务器重新启动时升级到 2012 后,列会跳跃 1000 个值,我们使用了此处显示的解决方法:http://www.codeproject.com/Tips/668042/SQL-Server-2012-Auto-Identity-Column-Value-Jump-Is (-t272) 来阻止这种情况发生,但让我们意识到 IDENTITY( 1, 1) 还不够好。
我们现在真正想要的是确保每个客户的数字都会增加,但它必须是永久性的,并且一旦分配就不能更改。
显然,一个序列将不再起作用,因为它需要每个客户,我们还需要对每个客户/用户强制执行唯一约束,并确保该值一旦分配就永远不会改变,如果用户被删除也不会改变(虽然这不应该发生,因为我们不会删除用户而是将它们标记为已归档,但我想保证这不会影响它)。
以下是我编写的可以生成数字的示例,但使用此方法或类似方法的最佳方法是什么从不同的会话同时创建。
ROW_NUMBER() OVER (ORDER BY i.UserId) + ISNULL((SELECT MAX(users.MembershipNumber)
FROM [User].Users users
WHERE users.Customers_CustomerId = i.Customers_CustomerId), 0)
编辑:澄清
很抱歉,我刚刚重新阅读了我的问题,但我没有说得足够清楚,我们不打算替换 UserId,我们对所有外键上使用的每个数据库标识符的差距和唯一性感到满意,我们正在寻找添加的是一个将显示给用户的 MembershipNumber,这就是为什么它需要按客户顺序排列,没有间隙,因为此会员号将用于提供给用户的卡上,因此需要是唯一的。
【问题讨论】:
-
您为什么介意差距或每个客户有一个系列?不就是某种身份证吗?您的解决方案可能有效,但我不是 SELECT MAX() 的粉丝,因为它只有在您将数据库设置为一直锁定时才真正有效。理想情况下,您会使用快照隔离来减少争用,但会引入这样的问题。就我个人而言,我只是按顺序进行,并接受差距。
-
Stop making assumptions about
IDENTITY,别再担心差距了——它们真的不是问题! -
感谢您的回复,我已经编辑了我的问题以澄清我的意思。
-
阅读您的编辑后,我仍然认为我的回答完全符合您的需求。如果您不这么认为,请在评论中告诉我,以便我尝试改进它。
标签: sql-server uniqueidentifier