Zasadniczo szukasz wzoru wstawiania lub aktualizowania czasami określane jako przewrotne
Polecam to:Wstaw lub zaktualizuj wzorzec dla serwera SQL — Sam Saffron
W przypadku procedury, która będzie dotyczyć pojedynczych wierszy, każda z tych transakcji będzie dobrze działać:
Pierwsze rozwiązanie Sama Saffrona (przystosowane do tego schematu):
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
Drugie rozwiązanie Sama Saffrona (dostosowane do tego schematu):
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
Nawet przy kreatywnym użyciu IGNORE_DUP_KEY
, nadal będziesz musiał użyć bloku wstawiania/aktualizacji lub instrukcji scalania.
- Kreatywne wykorzystanie 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'
);
Odpowiedź Scal dostarczona przez Spocka powinna zrobić to, co chcesz.
Scal niekoniecznie jest zalecane. Używam go, ale nigdy nie przyznam się do tego @AaronBertrand.
-
Zachowaj ostrożność w przypadku instrukcji MERGE SQL Server — Aaron Bertrand
-
Czy mogę zoptymalizować to oświadczenie scalające - Aaron Bertrand
-
Jeśli używasz widoków indeksowanych i MERGE, przeczytaj to! - Aaron Bertrand
-
Ciekawy błąd MERGE — Paul White
-
UPSERT Warunki wyścigu ze scalaniem