Equivalent of MySQL ON DUPLICATE KEY UPDATE in Sql Server

后端 未结 5 1134
走了就别回头了
走了就别回头了 2020-12-03 04:41

I am trying to find an equivalent of the following MySql query in Sql Server (2012)?

INSERT INTO mytable (COL_A, COL_B, COL_C, COL_D)
VALUES ( \'VAL_A\',\'VA         


        
5条回答
  •  囚心锁ツ
    2020-12-03 05:18

    You are basically looking for an Insert or Update pattern sometimes referred to as an Upsert.

    I recommend this: Insert or Update pattern for Sql Server - Sam Saffron

    For a procedure that will be dealing with single rows, either these transactions would work well:

    Sam Saffron's First Solution (Adapted for this schema):

    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
    

    Sam Saffron's Second Solution (Adapted for this schema):

    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
    

    Even with a creative use of IGNORE_DUP_KEY, you'd still be stuck having to use an insert/update block or a merge statement.

    • A creative use of IGNORE_DUP_KEY - Paul White @Sql_Kiwi
    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'
          );
    

    The Merge answer provided by Spock should do what you want.

    Merge isn't necessarily recommended. I use it, but I'd never admit that to @AaronBertrand.

    • Use Caution with SQL Server's MERGE Statement - Aaron Bertrand

    • Can I optimize this merge statement - Aaron Bertrand

    • If you are using indexed views and MERGE, please read this! - Aaron Bertrand

    • An Interesting MERGE Bug - Paul White

    • UPSERT Race Condition With Merge

提交回复
热议问题