Мне нужно получить поле идентификатора, сгенерированное SQL Server 2005. Обычно я просто использую SCOPE_IDENTITY или добавляю OUTPUT CLAUSE к вставке, однако ни один из этих методов не помогает в этой ситуации: так как триггер INSTEAD OF присоединен стол. Затем я рассмотрел @@ IDENTITY, но поскольку к таблице подключен еще один триггер, это тоже не годится. Поэтому я решил использовать IDENT_CURRENT. Однако, поскольку это небезопасно для сеанса, мне нужен какой-то способ убедиться, что никакой другой сеанс не может быть вставлен в таблицу, пока я не получу новый идентификатор. Я экспериментировал с использованием подсказок TABLOCK и HOLDLOCK, похоже, это работает, но я не администратор баз данных. Поэтому мой вопрос заключается в том, позволят ли использование подсказок TABLOCK и HOLDLOCK в SQL Server 2005 ПОЛНОСТЬЮ предотвратить вставки до конца транзакции?
Надеюсь, этот надуманный пример объяснит ситуацию. (Я понимаю, что функционально хранимая процедура может заменить оба триггера в этом случае.)
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;