SQL Server自动递增每个客户的身份(租户),没有空隙

时间:2015-05-10 06:59:23

标签: sql-server uniqueidentifier

我们有一个多租户数据库,它拥有多个客户,每个客户都拥有一组用户(简化示例,省略了从用户到客户的外键规范):

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作为会员编号,但是随着所有事情的增加,这个要求已经增长,这不再是两个选项原因:

  1. 在我们在每台服务器上升级到2012后,重新启动列会跳过1000个值,我们使用了此处显示的解决方法:http://www.codeproject.com/Tips/668042/SQL-Server-2012-Auto-Identity-Column-Value-Jump-Is(-t272)来阻止这种情况发生,但让我们意识到IDENTITY(1,1)不够好。

  2. 我们现在真正想要的是确保每个客户的数量增加,但必须是永​​久性的,一旦分配就不能改变。

  3. 显然,序列不会再次起作用,它需要按照客户的要求,我们还需要对每个客户/用户强制执行一个唯一约束,并确保一旦分配就永远不会更改该值,如果删除用户则不会更改(虽然这不应该发生,因为我们不会删除用户但是将其标记为已存档,但我想保证这不会影响它)。

    以下是我编写的可以生成数字的示例,但是使用此类或类似内容的最佳方式是确保每个客户/用户的唯一顺序值,而不会出现任何问题,因为用户可能是从不同的会议同时创建。

      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,这就是为什么它需要按顺序每个客户而没有间隙,因为这个会员号将用于提供给用户的卡,因此需要是唯一的。

3 个答案:

答案 0 :(得分:0)

由于您已经发现了Identity列的问题以及如何修复它,我不会说它不够好。
但是,它似乎不适合您的需求,因为您希望用户号码按每个客户递增。

我建议将User列保留为Identity列和表的主键,并添加另一列以按客户指定用户号。此列也是一个整数,其UDF结果的默认值将计算每个客户的下一个数字(see example in this post)。

您可以通过在users表上使用而不是更新触发器来保护该值不会发生变化。

这种方法可以保留单个列主键,您可以为每个客户提供唯一的顺序用户号。

<强>更新
显然,it is impossible to send column values to a default constraint.
但您仍然可以使用instead of insert触发器来实现目标。

答案 1 :(得分:0)

这是因为序列对象的默认缓存sqlserver实现。看到这个前一个主题 Identity increment is jumping in SQL Server database

如果差距是个问题,sql-server2012引入了Sequence对象。您可以使用NOCACHE声明这些内容,因此重新启动服务器不会产生间隙。

答案 2 :(得分:0)

我想分享一下我的想法。请参阅下文。

  1. 创建单独的表格,其中包含CustomerID和Count列,如下所示。

    CREATE TABLE dbo.CustomerSequence
    (
       @CustomerID int,
       @Count  int
    );
    
  2. 写下某种存储过程,如下所示。

    CREATE PROC dbo.usp_GetNextValueByCustomerID
          @CustomerID int,
          @Count int OUTPUT
    AS
    BEGIN
        UPDATE dbo.CustomerSequence
        SET @Count = Count += Count
        WHERE CustomerID = @CustomerID;
    
    END
    
  3. 只需通过传递CustomerID并从中获取下一个序列值来调用上述存储过程。