Sql server TSQL ID生成

Sql server TSQL ID生成,sql-server,tsql,Sql Server,Tsql,我有一个关于在TSQL中锁定的问题。假设我在下表中有一个 A(int id, varchar name) 其中id是主键,但不是标识列 我想使用以下伪代码在此表中插入一个值: lock (A) uniqueID = GenerateUniqueID() insert into A values (uniqueID, somename) unlock(A) 如何用T-SQL实现这一点?下一个id的计算应该在表A被锁定的情况下进行,以避免其他会话同时执行相同的操作并获得相同的id 您

我有一个关于在TSQL中锁定的问题。假设我在下表中有一个

A(int id, varchar name)
其中id是主键,但不是标识列

我想使用以下伪代码在此表中插入一个值:

lock (A)
  uniqueID = GenerateUniqueID()  
  insert into A values (uniqueID, somename)
unlock(A)
如何用T-SQL实现这一点?下一个id的计算应该在表A被锁定的情况下进行,以避免其他会话同时执行相同的操作并获得相同的id

您使用NEWID函数,不需要任何锁定机制

您告诉一个列为IDENTITY,并且不需要任何锁定机制

如果您手动生成这些ID,并且并行调用可能会生成相同的ID,则如下所示:


实际上只有三种方法可以做到这一点

将ID列更改为标识列,在该列中,每次插入时会自动增加某个值

将ID列更改为默认约束为NEWID或NEWSEQUENTIALID的GUID。然后,您可以插入自己的值,或者让表在每次插入时为您生成一个值

在每次插入时,启动一个事务。然后使用类似select maxid+1的方法获取下一个可用ID。如果可能,请在单个sql语句中执行此操作,以限制冲突的可能性

总的来说,大多数人更喜欢选项1。它快速、易于实现,而且大多数人都理解它

我倾向于使用选项2和我所使用的应用程序,因为我们倾向于扩展数据库。这意味着我们通常会使用多主应用程序。请注意,使用guid作为主键可能意味着您的索引经常被破坏


我会远离选项3,除非你别无选择。在这种情况下,我会看看数据模型是如何构造的,因为肯定会有问题。

如果您使用的是SQL2005+,您可以使用OUTPUT子句来执行您要求的操作,而无需任何类型的锁定。表Test1模拟您插入的表,由于输出需要一个临时表,而不是一个变量来保存结果,所以Result会这样做:

create table test1( test INT)

create table #result (LastValue INT)


insert into test1
output INSERTED.test into #result(test)
select GenerateUniqueID()

select LastValue from #result

@马库斯,你应该看看其他答案中提到的使用IDENTITY或NEWID。如果你绝对不能,这里有一个选择给你

DECLARE @NewID INT

BEGIN TRAN

SELECT  @NewID = MAX(ID) + 1
FROM    TableA (tablockx)

INSERT  TableA
        (ID, OtherFields)
VALUES  (@NewID, OtherFields)

COMMIT TRAN

如果要在生成ID时应用自定义逻辑,请将其包装到用户定义的函数中,然后使用用户定义的函数作为列的默认值。与提供的id生成器类似,这将减少并发问题,方法是将生成延迟到插入点,并借助插入锁定行为

create table ids  (id int, somval varchar(20))
Go
Create function GenerateUniqueID()
returns int as 
Begin
    declare @ret int
    select @ret =  max(isnull(id,1)) * 2 from ids
    if @ret is null set @ret = 2  
    return @ret
End
go
alter table ids add Constraint DF_IDS Default(dbo.GenerateUniqueID())  for Id

只是为了更新一篇旧文章。现在,SQL Server 2012可以使用名为Sequence的功能。序列的创建方式与函数基本相同,可以指定范围、方向、描述和滚动点。之后,可以调用方法的下一个值来生成范围内的下一个值

请参阅Microsoft提供的以下文档


嗯,我有两点意见:1。NEWID生成UUID项2。我不能使用这个身份type@KM:我知道-我只是用它作为示例来演示OUTPUT子句。我将修正我的示例,使其更加清晰
create table ids  (id int, somval varchar(20))
Go
Create function GenerateUniqueID()
returns int as 
Begin
    declare @ret int
    select @ret =  max(isnull(id,1)) * 2 from ids
    if @ret is null set @ret = 2  
    return @ret
End
go
alter table ids add Constraint DF_IDS Default(dbo.GenerateUniqueID())  for Id