Будет ли использовать подсказки TABLOCK и HOLDLOCK в SQL Server 2005 ПОЛНОСТЬЮ предотвращать вставки до конца транзакции?

Мне нужно получить поле идентификации, сгенерированное 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; 

Лучше всего будет подсказкой TABLOCKX, которая указывает, что эксклюзивная блокировка выполняется в таблице до завершения транзакции. Исключительные (X) блокировки предотвращают доступ к ресурсу посредством параллельных транзакций. Никакие другие транзакции не могут читать или изменять данные, заблокированные с помощью исключительной (X) блокировки.