2016-07-06 1 views
3

MyTable (MyTableId NVARCHAR (MAX) PRIMARY KEY, NumberOfInserts INTEGER) 테이블 구조로 가정하십시오.SQL Server 2016의 INSERT 또는 UPDATE를위한 안전한 솔루션

기존 레코드의 카운터를 증가 시키거나 NumberOfInserts에 0 값이없는 경우 새 레코드를 삽입해야하는 경우가 있습니다. 기본적으로

:

IF (MyTableId exists) 
    run UPDATE command 
ELSE 
    run INSERT command 

내 관심사는 경쟁 조건으로 인해 데이터가 손실되는 등

이 쓸 수있는 안전한 방법은 무엇입니까?

가능한 경우 100 % 정확해야하며 필요한 경우 속도를 희생 시키려합니다.

+0

MERGE 명령을 사용하면 업데이트, 삽입 및 삭제를 한꺼번에 수행 할 수 있습니다. 관측의 몇 가지, 제발 칼럼 '키'SQL 서버에서 예약어를 호출하지 마십시오. 또한 기본 키로 사용하고 있습니까? 그렇다면 NVARCHAR (MAX)는 정말 나쁜 생각입니다. –

답변

4

MERGE 문은 UPDATEINSERT (및 필요한 경우 DELETE)을 모두 수행 할 수 있습니다.

단일 원자 성 명령문인데도 경쟁 조건을 방지하려면 HOLDLOCK 쿼리 힌트를 사용하는 것이 중요합니다. Dan Guzman의 블로그 게시물 “UPSERT” Race Condition With MERGE이 있습니다. 여기서 그가 어떻게 작동 하는지를 자세히 설명하고이를 검증하기위한 테스트 스크립트를 제공합니다.

쿼리 자체는 솔직하다 : 행이 존재하고 별도의 UPDATEINSERT 문 경우

DECLARE @NewKey NVARCHAR(MAX) = ...; 

MERGE INTO dbo.MyTable WITH (HOLDLOCK) AS Dst 
USING 
(
    SELECT @NewKey AS NewKey 
) AS Src 
ON Src.NewKey = Dst.[Key] 
WHEN MATCHED THEN 
UPDATE 
SET NumberOfInserts = NumberOfInserts + 1 
WHEN NOT MATCHED THEN 
INSERT 
(
    [Key] 
    ,NumberOfInserts 
) 
VALUES 
(
    @NewKey 
    ,0 
); 

물론, 당신은 또한 별도의 검사로 명시 적으로 두 단계 접근 방법을 사용할 수 있습니다. 적절한 테이블 잠금 힌트를 사용하여 트랜잭션에서이 모든 내용을 래핑해야합니다.

자세한 내용은 Dan Guzman의 Conditional INSERT/UPDATE Race Condition을 참조하십시오.

+0

MERGE를 사용할 때는주의해야합니다. 문제가 많습니다. https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ –