Equivalent of MySQL ON DUPLICATE KEY UPDATE in Sql Server

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.

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.

Leave a Comment