我需要檢索由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;
所有這些併發症,而不是索引和完整的訪問序列化,只是用'upper(FirstName)'替換'FirstName'?只需加上一個約束,然後修復打破約束的客戶端代碼... – 2010-08-10 23:28:25
我同意Remus的觀點。爲什麼不使用存儲過程進行插入操作,然後在插入之前將FirstName解析爲大寫形式,或者將其形成應用程序? 即便如此,您可能會忽略大寫字母,但只要確保在選擇或比較大寫字母時使用大寫字母即可。或者,如果整個目的是區分大小寫的,只需將您的排序規則更改爲CI。 – Ryk 2010-08-10 23:55:15
我意識到我可以在這種情況下使用存儲過程,這就是爲什麼我worte「(我意識到,在功能上,存儲過程可以替換這兩種情況下的觸發器)。」這只是表明問題的一個簡單例子。是的,理想情況下將創建一個新的sp並更改客戶端代碼,但目前這不是一個選項。 – iamjud 2010-08-11 08:24:31