복붙노트

[SQL] 이를 이미 없으면 만 행을 삽입

SQL

이를 이미 없으면 만 행을 삽입

난 항상 그것을 달성하기 위해 다음과 같은 것을 사용했다 :

INSERT INTO TheTable
SELECT
    @primaryKey,
    @value1,
    @value2
WHERE
    NOT EXISTS
    (SELECT
        NULL
    FROM
        TheTable
    WHERE
        PrimaryKey = @primaryKey)

부하 일단 ...하지만, 기본 키 위반이 발생했습니다. 이것은 전혀이 테이블에 삽입하는 유일한 문입니다. 그래서 위의 문이 원자 아님을 의미합니까?

문제는이 마음대로 다시 거의 불가능하다는 것이다.

아마도 내가 다음과 같은 뭔가를 변경할 수 있습니다 :

INSERT INTO TheTable
WITH
    (HOLDLOCK,
    UPDLOCK,
    ROWLOCK)
SELECT
    @primaryKey,
    @value1,
    @value2
WHERE
    NOT EXISTS
    (SELECT
        NULL
    FROM
        TheTable
    WITH
        (HOLDLOCK,
        UPDLOCK,
        ROWLOCK)
    WHERE
        PrimaryKey = @primaryKey)

어쩌면 내가 잘못 잠금을 사용하거나 너무 많은 잠금 또는 무언가를 사용하고, 비록.

대답은 "IF (SELECT COUNT (*) ... INSERT"등을 제안하는 어디 stackoverflow.com에 다른 질문을 봐 왔지만, 나는 하나의 SQL 문은 원자 될 것이라고 (아마도 잘못된) 가정에서 항상이었다.

사람이 어떤 아이디어가 있습니까?

해결법

  1. ==============================

    1.무엇 "JFDI"패턴은 어떻습니까?

    무엇 "JFDI"패턴은 어떻습니까?

    BEGIN TRY
       INSERT etc
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() <> 2627
          RAISERROR etc
    END CATCH
    

    진심으로,이 특히 높은 볼륨으로, 빠르고 잠금없이 대부분의 동시입니다. 무엇 UPDLOCK이 에스컬레이트 전체 테이블이 잠겨 있다면?

    읽기 수업 4 :

  2. ==============================

    2.원래는 제시되지 않은 HOLDLOCK을 추가했다. 이 힌트없이 버전을 무시하십시오.

    원래는 제시되지 않은 HOLDLOCK을 추가했다. 이 힌트없이 버전을 무시하십시오.

    마찬가지로 지금까지 내가 걱정으로,이 충분해야한다 :

    INSERT INTO TheTable 
    SELECT 
        @primaryKey, 
        @value1, 
        @value2 
    WHERE 
        NOT EXISTS 
        (SELECT 0
         FROM TheTable WITH (UPDLOCK, HOLDLOCK)
         WHERE PrimaryKey = @primaryKey) 
    

    당신이 실제로 존재하는 경우 행을 업데이트하고 그렇지 않은 경우 삽입 할 경우에도, 당신은이 질문에 유용 할 수 있습니다.

  3. ==============================

    3.당신은 MERGE를 사용할 수 있습니다 :

    당신은 MERGE를 사용할 수 있습니다 :

    MERGE INTO Target
    USING (VALUES (@primaryKey, @value1, @value2)) Source (key, value1, value2)
    ON Target.key = Source.key
    WHEN MATCHED THEN
        UPDATE SET value1 = Source.value1, value2 = Source.value2
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (Name, ReasonType) VALUES (@primaryKey, @value1, @value2)
    
  4. ==============================

    4.이 "공식적인"방법인지는 모르겠지만, 당신은 INSERT를 시도하고 실패하면 UPDATE로 다시 떨어질 수있다.

    이 "공식적인"방법인지는 모르겠지만, 당신은 INSERT를 시도하고 실패하면 UPDATE로 다시 떨어질 수있다.

  5. ==============================

    5.첫째, 지역 사회에 대한 공헌 우리의 남자 @gbn 밖으로 큰 소리. 심지어 나는 그의 조언을 다음과 같은 자신을 발견하는 빈도를 설명하기 시작 할 수 없습니다.

    첫째, 지역 사회에 대한 공헌 우리의 남자 @gbn 밖으로 큰 소리. 심지어 나는 그의 조언을 다음과 같은 자신을 발견하는 빈도를 설명하기 시작 할 수 없습니다.

    어쨌든, 충분히 팬보이 - 보내고.

    아마도 그의 대답에 약간 추가하려면는 "강화". 사람들을 위해, 나처럼 <> 2627 시나리오에서 수행하는 것과 불안 느낌 왼쪽 (더 빈 CATCH이 옵션을 선택하지 않습니다). 나는 TechNet의에서이 작은 덩어리를 발견했다.

        BEGIN TRY
           INSERT etc
        END TRY
        BEGIN CATCH
            IF ERROR_NUMBER() <> 2627
              BEGIN
                    DECLARE @ErrorMessage NVARCHAR(4000);
                    DECLARE @ErrorSeverity INT;
                    DECLARE @ErrorState INT;
    
                    SELECT @ErrorMessage = ERROR_MESSAGE(),
                    @ErrorSeverity = ERROR_SEVERITY(),
                    @ErrorState = ERROR_STATE();
    
                        RAISERROR (
                            @ErrorMessage,
                            @ErrorSeverity,
                            @ErrorState
                        );
              END
        END CATCH
    
  6. ==============================

    6.나는 다른 방법을 사용하여 과거에 비슷한 작업을 완료했습니다. 첫째, 나는 차 키를 보유하는 변수를 선언합니다. 그리고 나는 그 값을 기록 찾습니다 SELECT 문의 출력하여 해당 변수를 채 웁니다. 그럼 내가 할 수 및 IF 문. 기본 키가 null 인 경우, 다음, 다른, 삽입 할 몇 가지 오류 코드를 반환합니다.

    나는 다른 방법을 사용하여 과거에 비슷한 작업을 완료했습니다. 첫째, 나는 차 키를 보유하는 변수를 선언합니다. 그리고 나는 그 값을 기록 찾습니다 SELECT 문의 출력하여 해당 변수를 채 웁니다. 그럼 내가 할 수 및 IF 문. 기본 키가 null 인 경우, 다음, 다른, 삽입 할 몇 가지 오류 코드를 반환합니다.

         DECLARE @existing varchar(10)
        SET @existing = (SELECT primaryKey FROM TABLE WHERE param1field = @param1 AND param2field = @param2)
    
        IF @existing is not null
        BEGIN
        INSERT INTO Table(param1Field, param2Field) VALUES(param1, param2)
        END
        ELSE
        Return 0
    END
    
  7. from https://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there by cc-by-sa and MIT license