sql server:这个嵌套是否足以从数据库中获取唯一的数字?

Mic*_*hel 1 sql sql-server database-design

我想从表中生成一个唯一的数字.它当然必须是线程安全的,所以当我检查最后一个数字并获得'3',然后将'4'存储在数据库中时,我不希望其他任何人只是在这两个动作之间(获取数字)并将其存储在数据库中一个更高的位置)也将'3'存回,然后还存储'4'

所以我想,把它放在这样的交易中:

begin transaction
        declare @maxNum int
        select @maxNum = MAX(SequenceNumber) from invoice
            where YEAR = @year
        if @maxNum is null
        begin
            set @maxNum = 0
        end
        set @maxNum = @maxNum + 1
        INSERT INTO [Invoice]
           ([Year]
           ,[SequenceNumber]
           ,[DateCreated])
     VALUES
           (@year
           ,@maxNum
           ,GETUTCDATE()
)

    commit transaction

    return @maxNum
Run Code Online (Sandbox Code Playgroud)

但我想知道,这就足够了,把它放在交易中?我的第一个想法是:它锁定了这个sp供其他人使用,但这是正确的吗?如何在第一步知道sql server知道要锁定什么?

这种结构是否会保证我没有其他人会select @maxnum在我updating the @maxnum有价值的时候做到这一点,并且在那一刻收到同样的@ maxnum就像我这样做我有麻烦.

我希望你理解我想要完成的事情,如果你知道我是否选择了正确的解决方案.

编辑:也被描述为'如何单线程存储过程'

mar*_*c_s 5

如果您想将年份和序列号存储在数据库中,并从中创建发票号,我将使用:

  • InvoiceYear列(完全可以计算为YEAR(InvoiceDate))
  • InvoiceID INT IDENTITY,你可以每年重置为1列
  • 创建一个计算InvoiceNumber列为:

    ALTER TABLE dbo.InvoiceTable
       ADD InvoiceNumber AS CAST(InvoiceYear AS VARCHAR(4)) + '-' +
               RIGHT('000000' + CAST(InvoiceID AS VARCHAR(6)), 6) PERSISTED
    
    Run Code Online (Sandbox Code Playgroud)

这样,您就可以自动获取发票号码:

2010-000001
......
2010-001234
......
2010-123456
Run Code Online (Sandbox Code Playgroud)

当然,如果您需要超过6位数(= 100万张发票) - 只需调整列的RIGHT()CAST()语句即可InvoiceID.

此外,由于这是一个持久计算列,您可以将其编入索引以便快速检索.

这样:不必担心并发,存储过程,事务和类似的事情 - SQL Server将为您做到这一点 - 免费!