2014-06-17 81 views
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列中的重複項。任何想法如何改變它?

+2

爲什麼你需要第二個自動遞增列?這是一個簡單的例子嗎?可以有一個更容易維護的替代解決方案。 – GarethD

+0

@GarethD - 這是一個簡單的例子。每家公司都需要有一個唯一的ID。所以xtable也會有一個CompanyID fk – Aducci

+0

哪個SQL Server? 2008年[R2],2012年,2014年? –

回答

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] 

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

使用這些鎖的缺點是您會發生死鎖。您應該在此列上有一個唯一的約束/索引,因爲這樣可以防止重複,但是在滿足競爭條件時也會導致異常。最終,無論你選擇什麼方法,你都需要做出某種犧牲。

+3

如果多個插入語句並行運行,這樣做會工作嗎? –

+0

對不起,我不清楚,我假設插入只有1行。當多個插入語句同時發生時,我收到重複的信息 – Aducci

+0

@Aducci這就是爲什麼答案是使用'IDENTITY'列而不是自定義的一個 – Lamak

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); 
+1

我無法測試此解決方案,但我很欣賞序列信息。我不知道他們 – Aducci

+0

@Aducci:你試過了嗎?您是否嘗試過測試此解決方案時遇到問題?如果是,那麼你能告訴我你得到了什麼錯誤嗎? –