维护自定义自动增量列

时间:2014-06-17 15:15:19

标签: sql sql-server sql-server-2012 sql-server-2014

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


表格

xtable(ID identity,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列中的重复项。关于如何改变它的任何想法?

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:1)

SQL Server 2012 +:

我会使用sequences

首先,我会创建一个新序列

CREATE SEQUENCE dbo.XTable_XID 
START WITH 1 -- You should replace the starting value 
INCREMENT BY 1
-- CACHE 50; -- Optimization: read documentation first 
GO

然后我会使用NEXT VALUE FOR生成新值:

-- #1 I would use this function when I insert rows `into dbo.XTable` 
INSERT INTO [dbo].[XTable] (Col1, Col2, Col3, ..., XID)
VALUES ('A', 123, 1000.50, (NEXT VALUE FOR dbo.XTable_XID));

-- #2: Also, you could rewrite the trigger thus:
insert into [xtable] (XID)
select (NEXT VALUE FOR dbo.XTable_XID)
from inserted [i]

我正在使用第一种方法,如果它仅用于生成这些ID,则可以删除该触发器。我会使用解决方案#1。

+

我会创建一个唯一的索引:

CREATE UNIQUE INDEX IUN_XTable_XID 
ON dbo.XTable (XID);

答案 2 :(得分:1)

我最终创建了另一个表来存储最后一个增量。在触发器中,在事务内部,我从新表中选择提示(UPDLOCKROWLOCK)。


表格

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]