Você está basicamente procurando por um padrão de inserção ou atualização às vezes chamado de Upsert.
Eu recomendo isto:Inserir ou atualizar padrão para Sql Server - Sam Saffron
Para um procedimento que lida com linhas únicas, essas transações funcionariam bem:
Primeira solução de Sam Saffron (adaptado para este esquema):
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
Segunda solução de Sam Saffron (adaptado para este esquema):
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
Mesmo com um uso criativo de
IGNORE_DUP_KEY
, você ainda ficaria preso ao usar um bloco de inserção/atualização ou uma instrução de mesclagem. - Um uso criativo de 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'
);
A resposta Merge fornecida por Spock deve fazer o que você deseja.
Mesclar não é necessariamente recomendado. Eu uso, mas nunca admitiria isso para @AaronBertrand.
-
Tenha cuidado com a instrução MERGE do SQL Server - Aaron Bertrand
-
Posso otimizar esta declaração de mesclagem - Aaron Bertrand
-
Se você estiver usando visualizações indexadas e MERGE, leia isto! - Aaron Bertrand
-
Um Bug Interessante de MERGE - Paul White
-
Condição de corrida UPSERT com mesclagem