0

我有一个带有 ID(身份)和 XID(int)的表,这是我的自定义自动增量列。我正在使用而不是插入触发器来维护 XID,但我得到了重复。


桌子

xtable(ID 身份,XID int)


触发器- 而不是插入

insert into [xtable] (XID)
select [x].[NextavailableID]
from inserted [i]
cross apply
(
  select coalesce(max([t].[XID]), 0) + 1 [NextavailableID]
  from [xtable] [t]
) [x];

假设插入 = 1 行。

此触发器不会阻止 XID 列中的重复。关于如何改变它的任何想法?

4

2 回答 2

2

问题是,在插入多行的情况下,您对所有行使用相同的下一个可用 ID,您需要添加ROW_NUMBER()以确保 xid 在插入中是唯一的:

insert into [xtable] (XID)
select [x].[NextavailableID] + ROW_NUMBER() OVER (ORDER BY i.ID)
from inserted [i]
cross apply
(
  select coalesce(max([t].[XID]), 0) [NextavailableID]
  from [xtable] [t] WITH (TABLOCK, HOLDLOCK)
) [x];

关于防止重复,您可以xtable在获取最大值时使用表提示来锁定xid

使用这些锁的缺点是会出现死锁。您应该在此列上有一个唯一的约束/索引,因为这将防止重复,但是在满足竞争条件时也会导致异常。最终,无论您选择哪种方法,您都需要做出某种牺牲。

于 2014-06-17T15:18:55.133 回答
1

我最终创建了另一个表来存储最后一个增量。在触发器中,在事务中,我从带有提示 ( UPDLOCK, ROWLOCK) 的新表中进行选择。


桌子

Info (LastId int)

触发器- 而不是插入

declare @nextId int;

begin tran t1

  set @nextId = (select top 1 LastId from Info with (UPDLOCK, ROWLOCK)) + 1;

  update Info set LastId = nextId;

commit tran t1

insert into [xtable] (XID)
select @nextId
from inserted [i] 

于 2014-06-18T13:02:40.080 回答