Ceci est quelque chose qui m'ennuie à propos de MSSQL (rant on my blog). Je souhaite que MSSQL pris en charge upsert
.
@ code de Darlie-O est une bonne façon dans les anciennes versions SQL (1 vote), mais il est encore essentiellement deux opérations d'entrées-sorties (le exists
, puis le update
ou insert
)
Il y a une façon un peu mieux sur this post, essentiellement:
--try an update
update tablename
set field1 = 'new value',
field2 = 'different value',
...
where idfield = 7
--insert if failed
if @@rowcount = 0 and @@error = 0
insert into tablename
(idfield, field1, field2, ...)
values (7, 'value one', 'another value', ...)
Cela réduit à une des opérations IO si elle est une mise à jour, ou deux si un insert.
MS SQL2008 introduit merge
de SQL: 2003 standard:
merge tablename as target
using (values ('new value', 'different value'))
as source (field1, field2)
on target.idfield = 7
when matched then
update
set field1 = source.field1,
field2 = source.field2,
...
when not matched then
insert (idfield, field1, field2, ...)
values (7, source.field1, source.field2, ...)
Maintenant, il est vraiment une seule opération IO, mais le code terrible :-(
Super, merci! Enregistre le Select et n'a souvent même pas besoin d'une teransaction dans des situations où je peux être sûr qu'entre Update et "my" insert, il n'y a pas d'autre insert pour cette clé. –
@Michael Il vaut mieux avoir un index unique sur cette table et gérer les erreurs de clé en double si vous allez utiliser cette solution. –
@Keith Votre instruction de fusion ne fonctionne pas. 'MERGE' ne supporte pas la clause' WHERE', vous devez réécrire cela en utilisant 'USING' et' ON'. De plus, à moins d'ajouter 'WITH (HOLDLOCK)', il y a une course et des 'INSERT' simultanés peuvent se produire, l'un d'entre eux échouant en raison du conflit de clé. –