2010-08-10 1 views
4

SQL Server 2005에서 생성 된 ID 필드를 검색해야합니다. 일반적으로 SCOPE_IDENTITY를 사용하거나 OUTPUT CLAUSE를 삽입에 추가하지만 이러한 방법으로는이 두 가지 방법 모두 도움이되지 않습니다. INSTEAD OF 트리거가 표. 다음으로는 @@ IDENTITY를 고려했지만 테이블에 다른 트리거가 연결되어 있기 때문에 이것은 좋지 않습니다. 그래서 나는 IDENT_CURRENT를 써야한다고 생각했습니다. 그러나 이것은 세션 안전하지 않기 때문에 새로운 ID를 검색 할 때까지 다른 세션을 테이블에 삽입 할 수 없도록하는 방법이 필요합니다. 나는 TABLOCK과 HOLDLOCK 힌트를 사용하여 실험했는데, 이것은 효과가있는 것으로 보이지만 나는 DBA가 아닙니다. 그래서 내 질문은 SQL Server 2005에서 TABLOCK 및 HOLDLOCK 힌트를 사용하여 완전히 트랜잭션이 끝날 때까지 삽입을 방지 할 것입니다?SQL Server 2005에서 TABLOCK 및 HOLDLOCK 힌트 사용 트랜잭션이 끝날 때까지 삽입이 완전히 금지됩니까?

이 인위적인 예제가 상황을 설명하기를 바랍니다. (I는, 기능적으로, 저장 프로 시저,이 경우 두 트리거를 대체 할 수 있음을 알고 있습니다.)

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

이 모든 복잡성은 인덱스 대신 'FirstName'을 'upper (FirstName)'로 대체하는 완벽한 액세스 직렬화입니까 ?? 제약 조건을 넣은 다음 제약 조건을 위반하는 클라이언트 측 코드를 수정하십시오. –

+1

Remus에 동의합니다. 왜 삽입 프로 시저를 사용하지 않습니까? 그리고 삽입 전에 FirstName을 대문자로 구문 분석하거나 응용 프로그램을 구성합니까? 그렇다고해도 대문자를 무시할 수도 있지만 대문자로 선택하거나 비교할 때 확인하십시오. 또는 전체 목적이 대소 문자를 구별하는 경우 CI에 대한 데이터 정렬 만 변경하십시오. – Ryk

+1

이 경우 저장 프로 시저를 사용할 수 있다는 것을 알게되었습니다. "(필자는 기능적으로 저장 프로 시저가이 경우 두 트리거를 모두 대체 할 수 있음을 깨달았습니다.)" 이것은 문제를 보여주는 상황의 단순한 예입니다. 예, 이상적으로 새로운 sp가 만들어지고 클라이언트 코드가 변경되었지만 지금은 옵션이 아닙니다. – iamjud

답변

2

이 가장 좋은 방법은 트랜잭션이 완료 될 때까지 배타적 잠금이 테이블에 촬영되는 지정 TABLOCKX 힌트가 될 것입니다 . 배타 (X) 잠금은 동시 트랜잭션에 의한 자원 액세스를 금지합니다. 독점 (X) 잠금으로 잠긴 데이터는 다른 트랜잭션으로 읽거나 수정할 수 없습니다.

+0

독서는 괜찮습니다. X가없는 태블락으로 충분합니다. – usr

+0

@usr -이 질문에 대한 답변을 말씀 하시겠습니까? (SQL Server 2005의 TABLOCK 및 HOLDLOCK 힌트를 사용하면 트랜잭션이 끝날 때까지 삽입이 완전히 금지됩니까?) "예"입니까? – Colin

+0

@Colin 나는 그렇게 생각한다. 나는 정확하게이 해결책을지지하지는 않지만 작동 할 것이다. – usr

관련 문제