In pratica stai cercando un schema di inserimento o aggiornamento a volte indicato come Upsert.
Consiglio questo:Inserisci o Aggiorna pattern per Sql Server - Sam Saffron
Per una procedura che si occuperà di singole righe, queste due transazioni funzionerebbero bene:
La prima soluzione di Sam Saffron (adattata per questo 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
La seconda soluzione di Sam Saffron (adattata per questo 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
Anche con un uso creativo di IGNORE_DUP_KEY
, saresti ancora bloccato a dover utilizzare un blocco di inserimento/aggiornamento o un'istruzione di unione.
- Un uso creativo di 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'
);
La risposta Unisci fornita da Spock dovrebbe fare quello che vuoi.
Unisci non è necessariamente raccomandato. Lo uso, ma non lo ammetterei mai con @AaronBertrand.
-
Usare cautela con l'istruzione MERGE di SQL Server - Aaron Bertrand
-
Posso ottimizzare questa dichiarazione di unione - Aaron Bertrand
-
Se stai utilizzando viste indicizzate e MERGE, leggi questo! - Aaron Bertrand
-
Un interessante bug di MERGE - Paul White
-
Condizione di gara UPSERT con unione