使用DB处理递增数

时间:2013-09-07 08:24:23

标签: sql-server-2008

我们要求说,当我们将新人带入数据库时​​,我们需要为他们分配一个唯一的号码。系统上线时,此数字将从定义的数字开始。因此,如果客户说“从500,000开始!”,那么第一个分配的ID将是500000。

轻松 - 自动增加恶魔。

但是,此IDAccount Number,会发送到外部客户端以将此人链接到帐户。一个想法可能是使用auto inc主键,但我认为将PK用作面向外部的“人员号码”是很糟糕的。

有人提到有一个表,有一个auto inc pk,以及我们正在添加号码的人员表的id。但这似乎很奇怪。

我的想法是在我们的settings表中添加一个新列,它实际上只有一行,并包含系统的系统设置。该列为INT,称为NextAvailableId。所有行都有Version列,TimestampRowVersion)。

我的计划是创建一个名为GetNextId的函数,它只会执行以下操作:

  1. 创建一个名为@AssignedID
  2. 的变量
  3. 创建一个名为@Version
  4. 的变量
  5. 从设置表中获取NextAvailableId以及版本。
  6. Set AssignedID = NextAvailableId
  7. 更新设置表,设置NextAvailableId = AssignedID + 1 WHERE version = @Version
  8. 检查更新的行数。如果它是1,那么在另一个进程获取ID之前,我们设法获取最新的ID,增加它并将其保存回表中。
  9. 如果更新的行数为零 - 那么有人在我们面前抓了一个数字......所以,再试一次,直到我们有一个更新的行。
  10. 这听起来像是一个安全有效的计划,可以将“帐号”分配给我的人吗?

    请注意,它不是真正的人或帐户代码。它是一个供应商ID,需要应用于某个人才能存储在单独的系统中。仅使用人员和帐户作为(差)示例。

    我需要做的是找到一种方法来处理“帐号”的唯一分配。如果手动方式是一个坏主意,并且有更好的方法 - 那么这将对我有很大帮助。

1 个答案:

答案 0 :(得分:2)

虽然我不同意你手动增加最后一个ID的方法,但我同意marc_s你需要注意并发性。

我最快的方法是将您的函数中的事务与READ UNCOMMITTED组合为隔离级别和小Mutex字段。这是伪代码:

  1. 使用READ UNCOMMITED
  2. 开始新交易
  3. 检查是互斥锁标志= 0(没有其他方法正在运行)
  4. 如果flag = 1,则循环
  5. 如果flag = 0,则设置为1
  6. 获取最后一个ID
  7. 随意增加
  8. 在表格中设置最后一个ID
  9. 将互斥锁标志设置为0
  10. 返回新的ID /提交事务
  11. READ UNCOMMITED将允许多次执行检查Mutex标志的值,而其他事务仍在运行且尚未提交。

    编辑:

    我建议您添加一个新列,其中包含您使用的默认值而不是PK。示例如下:

    CREATE FUNCTION dbo.GetLastId()
    RETURNS INT
    AS
        BEGIN
            RETURN SELECT MAX(AccountID) + 1 FROM dbo.tblUsers
        END
    
    -- Set the default value to the column
    ALTER TABLE dbo.tblUsers
    ADD AccountID SET DEFAULT (dbo.GetLastId())