복붙노트

[SQL] 는 SQL 서버에서 MySQL을 ON DUPLICATE KEY UPDATE의 등가

SQL

는 SQL 서버에서 MySQL을 ON DUPLICATE KEY UPDATE의 등가

나는 (2012)는 SQL Server의 다음과 MySQL의 쿼리의 동등한를 찾기 위해 노력하고 있어요?

INSERT INTO mytable (COL_A, COL_B, COL_C, COL_D)
VALUES ( 'VAL_A','VAL_B', 'VAL_C', 'VAL_D')
ON DUPLICATE KEY UPDATE COL_D= VALUES(COL_D);

누구든지 도움이 수 있습니까?

추신. 나는 MERGE 쿼리는 유사한 기능을 가지고 읽었습니다,하지만 난 그 매우 다른 구문을 찾을 수 있습니다.

해결법

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

    1.당신은 기본적으로 때로는 Upsert로 불리는 삽입 또는 업데이트 패턴을 찾고 있습니다.

    당신은 기본적으로 때로는 Upsert로 불리는 삽입 또는 업데이트 패턴을 찾고 있습니다.

    SQL Server의 경우 삽입 또는 업데이트 패턴 - 샘 사프란 :이 추천

    하나의 행이 처리 될 절차를 들어 하나 이러한 거래는 잘 작동 :

    샘 사프란 최초의 솔루션 (이 스키마에 대한 적응)

    begin tran
    if exists (
      select * 
        from mytable with (updlock,serializable) 
        where col_a = @val_a
          and col_b = @val_b
          and col_c = @val_c
      )
      begin
        update mytable
          set col_d = @val_d
          where col_a = @val_a
            and col_b = @val_b
            and col_c = @val_c;
      end
    else
      begin
        insert into mytable (col_a, col_b, col_c, col_d)
          values (@val_a, @val_b, @val_c, @val_d);
      end
    commit tran
    

    샘 사프란의 두 번째 솔루션 (이 스키마에 대한 적응)

    begin tran
      update mytable with (serializable)
        set col_d = @val_d
          where col_a = @val_a
            and col_b = @val_b
            and col_c = @val_c;
      if @@rowcount = 0
        begin
            insert into mytable (col_a, col_b, col_c, col_d)
              values (@val_a, @val_b, @val_c, @val_d);
         end
    commit tran
    

    심지어 IGNORE_DUP_KEY의 창조적 인 사용으로, 당신은 여전히 ​​삽입 / 업데이트 블록 또는 병합 문을 사용하는 데 걸린 것.

    update mytable
      set col_d = 'val_d'
      where col_a = 'val_a'
        and col_b = 'val_b'
        and col_c = 'val_c';
    
    insert into mytable (col_a, col_b, col_c, col_d)
      select 'val_a','val_b', 'val_c', 'val_d'
      where not exists (select * 
        from mytable with (serializable) 
        where col_a = 'val_a'
          and col_b = 'val_b'
          and col_c = 'val_c'
          );
    

    스팍 제공하는 병합 대답은 당신이 원하는해야한다.

    병합은 반드시 권장하지 않습니다. 나는 그것을 사용하지만, 나는 @AaronBertrand에 그것을 인정하지 않을 것입니다.

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

    2.이 시도... 나는 시도하고 어디 SQL 병합 문에 상황에 대해 설명하는 주석을 추가했습니다. 출처 : MSDN : 병합 문

    이 시도... 나는 시도하고 어디 SQL 병합 문에 상황에 대해 설명하는 주석을 추가했습니다. 출처 : MSDN : 병합 문

    병합 문을 사용하면 병합 무엇 열을 사용하도록 지시 할 수있는 ON DUPLICATE KEY UPDATE 문을 다릅니다.

    CREATE TABLE #mytable(COL_A VARCHAR(10), COL_B VARCHAR(10), COL_C VARCHAR(10), COL_D VARCHAR(10))
    INSERT INTO #mytable VALUES('1','0.1', '0.2', '0.3'); --<These are the values we'll be updating
    
    SELECT * FROM #mytable --< Starting values (1 row)
    
        MERGE #mytable AS target --< This is the target we want to merge into
        USING ( --< This is the source of your merge. Can me any select statement
            SELECT '1' AS VAL_A,'1.1' AS VAL_B, '1.2' AS VAL_C, '1.3' AS VAL_D --<These are the values we'll use for the update. (Assuming column COL_A = '1' = Primary Key)
            UNION
            SELECT '2' AS VAL_A,'2.1' AS VAL_B, '2.2' AS VAL_C, '2.3' AS VAL_D) --<These values will be inserted (cause no COL_A = '2' exists)
            AS source (VAL_A, VAL_B, VAL_C, VAL_D) --< Column Names of our virtual "Source" table
        ON (target.COL_A = source.VAL_A) --< This is what we'll use to find a match "JOIN source on Target" using the Primary Key
        WHEN MATCHED THEN --< This is what we'll do WHEN we find a match, in your example, UPDATE COL_D = VALUES(COL_D);
            UPDATE SET
                target.COL_B = source.VAL_B,
                target.COL_C = source.VAL_C,
                target.COL_D = source.VAL_D
        WHEN NOT MATCHED THEN --< This is what we'll do when we didn't find a match
        INSERT (COL_A, COL_B, COL_C, COL_D)
        VALUES (source.VAL_A, source.VAL_B, source.VAL_C, source.VAL_D)
        --OUTPUT deleted.*, $action, inserted.* --< Uncomment this if you want a summary of what was inserted on updated.
        --INTO #Output  --< Uncomment this if you want the results to be stored in another table. NOTE* The table must exists
        ;
    SELECT * FROM #mytable --< Ending values (2 row, 1 new, 1 updated)
    

    희망이 도움이

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

    3.저장 프로 시저는 하루에 저장됩니다.

    저장 프로 시저는 하루에 저장됩니다.

    여기에 나는 COL_A과 COL_B 고유 열이 있고 INT의 유형 가정 NB! ATM 그렇게 구문의 보증 정확성 할 수 없습니다 SQL 서버 인스턴스가 없습니다. 최신 정보! 여기 SQLFIDDLE에 대한 링크입니다

     CREATE TABLE mytable
    (
    COL_A int UNIQUE,
    COL_B int UNIQUE,
    COL_C int,
    COL_D int,
    )
    
    GO
    
    INSERT INTO mytable (COL_A, COL_B, COL_C, COL_D)
    VALUES (1,1,1,1),
    (2,2,2,2),
    (3,3,3,3),
    (4,4,4,4);
    GO
    
    CREATE PROCEDURE updateDuplicate(@COL_A INT, @COL_B INT, @COL_C INT, @COL_D INT)
    AS
    BEGIN
        DECLARE @ret INT
        SELECT @ret = COUNT(*) 
        FROM mytable p 
        WHERE p.COL_A = @COL_A 
            AND p.COL_B = @COL_B
    
         IF (@ret = 0) 
            INSERT INTO mytable (COL_A, COL_B, COL_C, COL_D)
            VALUES ( @COL_A, @COL_B, @COL_C, @COL_D)
    
         IF (@ret > 0)
            UPDATE mytable SET COL_D = @COL_D WHERE col_A = @COL_A AND COL_B = @COL_B  
    END;
    GO
    

    그리고 대신 업데이트 문에 필요한 값이 프로 시저를 호출

    exec updateDuplicate 1, 1, 1, 2
    GO
    SELECT * from mytable
    GO
    
  4. ==============================

    4.당신은 INSTEAD OF 트리거 사용하여 거의 동일한 동작을 시뮬레이션 할 수 있습니다 :

    당신은 INSTEAD OF 트리거 사용하여 거의 동일한 동작을 시뮬레이션 할 수 있습니다 :

    CREATE TRIGGER tMyTable ON MyTable
    INSTEAD OF INSERT
    AS
        BEGIN
            SET NOCOUNT ON;
    
            SELECT i.COL_A, i.COL_B, i.COL_C, i.COL_D, 
                CASE WHEN mt.COL_D IS NULL THEN 0 ELSE 1 END AS KeyExists 
                INTO #tmpMyTable
                FROM INSERTED i
                LEFT JOIN MyTable mt
                ON i.COL_D = mt.COL_D;
    
            INSERT INTO MyTable(COL_A, COL_B, COL_C, COL_D)
                SELECT COL_A, COL_B, COL_C, COL_D
                    FROM #tmpMyTable
                    WHERE KeyExists = 0;
    
            UPDATE mt
                SET mt.COL_A = t.COL_A, mt.COL_B = t.COL_B, mt.COL_C = t.COL_C
                FROM MyTable mt 
                    INNER JOIN #tmpMyTable t 
                    ON mt.COL_D = t.COL_D AND t.KeyExists = 1;
        END;
    

    여기 SqlFiddle

    작동 원리

    분출 포인트

    NB

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

    5.이 SQL 서버에 중복 KEY UPDATE 상당 없습니다,하지만 당신은 합병 사용할 수 있습니다 및 SQL Server의 일치 할 때, 수행 여기 봐 얻을 : 병합을 사용하여 여러 작업

    이 SQL 서버에 중복 KEY UPDATE 상당 없습니다,하지만 당신은 합병 사용할 수 있습니다 및 SQL Server의 일치 할 때, 수행 여기 봐 얻을 : 병합을 사용하여 여러 작업

  6. from https://stackoverflow.com/questions/27076348/equivalent-of-mysql-on-duplicate-key-update-in-sql-server by cc-by-sa and MIT license