To jest coś, co denerwuje mnie na temat MSSQL (rant on my blog). Szkoda, że MSSQL nie obsługuje upsert
.
@ kodu Dillie-O jest dobrym sposobem, w starszych wersjach SQL (+1 głos), ale nadal jest w zasadzie dwie operacje IO (the exists
a następnie update
lub insert
)
Jest nieco lepszy sposób na this post, zasadniczo:
--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', ...)
zmniejsza to do jednej operacji IO, czy jest to zmiana, lub dwa jeśli wkładka.
MS Sql2008 wprowadza merge
z SQL: standard 2003:
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, ...)
Teraz to naprawdę tylko jedna operacja IO, ale kod straszne :-(
Świetnie, dzięki! Zapisuje Select i często nawet nie wymaga teran akcji w sytuacjach, w których mogę być pewien, że pomiędzy Update a "my" insertem nie ma innej wstawki dla tego klucza. –
@Michael Lepiej mieć unikalny indeks w tej tabeli i obsługę błędów powtarzających się kluczy, jeśli zamierzasz używać tego rozwiązania. –
@Keith Instrukcja łączenia nie działa. "MERGE" nie obsługuje klauzuli "WHERE", musisz przepisać to używając 'USING' i' ON'. Ponadto, jeśli nie dodasz 'WITH (HOLDLOCK)', istnieje wyścig i jednoczesne 'INSERT's może się zdarzyć, a jeden z nich zawiedzie ze względu na kluczowe zderzenie. –