Vous recherchez essentiellement un modèle d'insertion ou de mise à jour parfois appelé Upsert.
Je recommande ceci :Modèle d'insertion ou de mise à jour pour Sql Server - Sam Saffron
Pour une procédure qui traitera des lignes uniques, ces transactions fonctionneront bien :
Première solution de Sam Saffron (adapté pour ce schéma) :
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
Deuxième solution de Sam Saffron (adapté pour ce schéma) :
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
Même avec une utilisation créative de IGNORE_DUP_KEY
, vous seriez toujours obligé d'utiliser un bloc d'insertion/mise à jour ou une instruction de fusion.
- Une utilisation créative 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'
);
La réponse Merge fournie par Spock devrait faire ce que vous voulez.
Fusionner n'est pas forcément recommandé. Je l'utilise, mais je ne l'admettrai jamais à @AaronBertrand.
-
Soyez prudent avec l'instruction MERGE de SQL Server - Aaron Bertrand
-
Puis-je optimiser cette déclaration de fusion - Aaron Bertrand
-
Si vous utilisez des vues indexées et MERGE, veuillez lire ceci ! -Aaron Bertrand
-
Un bug de MERGE intéressant - Paul White
-
Condition de concurrence UPSERT avec fusion