2010-08-10 30 views
4

我需要檢索由SQL Server 2005生成的標識字段。通常我只是使用SCOPE_IDENTITY或向插入添加一個OUTPUT CLAUSE,但是在這種情況下,這兩種方法都不能解決問題:因爲INSTEAD OF觸發器附加到表。接下來我考慮了@ @ IDENTITY,但由於還有另一個觸發器附加在表上,所以這也不好。所以我想我必須使用IDENT_CURRENT。然而,因爲這不是會話安全的,我需要一些方法來確保沒有其他會話可以插入表中,直到我已經檢索到新的ID。我已經嘗試過使用TABLOCK和HOLDLOCK提示,這似乎工作,但我不是DBA。所以我的問題是,將使用SQL Server 2005中的TABLOCK和HOLDLOCK提示完全防止插入,直到事務結束?在SQL Server 2005中使用TABLOCK和HOLDLOCK提示是否完全防止插入直到事務結束?

希望這個人爲的例子能解釋這種情況。 (我知道,在功能上,存儲過程可能在這種情況下,更換這兩個觸發器。)

CREATE TABLE Person 
(
PersonID INT IDENTITY PRIMARY KEY, 
FirstName VARCHAR(50) 
); 
GO 

CREATE TABLE PersonHistory 
(
PersonHistoryID INT IDENTITY(5,1) PRIMARY KEY, 
PersonId INT, 
FirstName VARCHAR(50) 
); 
GO 

CREATE TRIGGER PersonAudit ON Person 
AFTER Insert 
AS 
INSERT INTO PersonHistory (PersonID, FirstName) 
SELECT Inserted.PersonID, Inserted.FirstName 
FROM Inserted; 
GO 

CREATE TRIGGER PersonCleaner ON Person 
INSTEAD OF Insert 
AS 
INSERT INTO Person (FirstName) 
SELECT UPPER(Inserted.FirstName) 
FROM Inserted; 
GO 

BEGIN TRAN; 

INSERT INTO Person WITH (TABLOCK, HOLDLOCK) (FirstName) 
VALUES ('George'); 

--SELECT @@IDENTITY AS '@@IDENTITY'; -- 5 
--SELECT IDENT_CURRENT('Person') AS 'IDENT_CURRENT'; -- 1 
--SELECT SCOPE_IDENTITY() AS 'SCOPE_IDENITIY'; -- NULL 

DECLARE @PersonID int; 
SELECT @PersonID = IDENT_CURRENT('Person'); 
SELECT @PersonID; -- 1 

COMMIT TRAN; 

--SELECT * FROM Person; 
--SELECT * FROM PersonHistory; 

DROP TABLE Person; 
DROP TABLE PersonHistory; 
+2

所有這些併發症,而不是索引和完整的訪問序列化,只是用'upper(FirstName)'替換'FirstName'?只需加上一個約束,然後修復打破約束的客戶端代碼... – 2010-08-10 23:28:25

+1

我同意Remus的觀點。爲什麼不使用存儲過程進行插入操作,然後在插入之前將FirstName解析爲大寫形式,或者將其形成應用程序? 即便如此,您可能會忽略大寫字母,但只要確保在選擇或比較大寫字母時使用大寫字母即可。或者,如果整個目的是區分大小寫的,只需將您的排序規則更改爲CI。 – Ryk 2010-08-10 23:55:15

+1

我意識到我可以在這種情況下使用存儲過程,這就是爲什麼我worte「(我意識到,在功能上,存儲過程可以替換這兩種情況下的觸發器)。」這只是表明問題的一個簡單例子。是的,理想情況下將創建一個新的sp並更改客戶端代碼,但目前這不是一個選項。 – iamjud 2010-08-11 08:24:31

回答

2

你最好的選擇將是TABLOCKX提示其指定直到交易完成的排它鎖採取表。獨佔(X)鎖定阻止併發事務對資源的訪問。沒有其他事務可以讀取或修改使用獨佔(X)鎖定鎖定的數據。

+0

但是閱讀還行。沒有X的TABLOCK就足夠了。 – usr 2012-05-13 22:30:56

+0

@usr - 那麼你是說這個問題的答案(將使用SQL Server 2005中的TABLOCK和HOLDLOCK提示完全防止插入,直到事務結束?)是「是」? – Colin 2013-01-15 14:09:02

+0

@科林我覺得這樣。我並不是完全倡導這種解決方案,但它會起作用。 – usr 2013-01-15 16:42:53

相關問題