Próbuję zaktualizować tabelę o tablicę wartości. Każdy element w tablicy zawiera informacje pasujące do wiersza w tabeli w bazie danych SQL Server. Jeśli wiersz już istnieje w tabeli, aktualizujemy ten wiersz o informacje w podanej tablicy. W przeciwnym razie wstawiamy nowy wiersz do tabeli. Zasadniczo opisałem upsert.
Teraz staram się to osiągnąć w procedurze przechowywanej, która przyjmuje parametr XML. Powodem, dla którego używam XML, a nie parametrów o wartościach przechowywanych w tabeli, jest to, że robiąc to drugie, będę musiał utworzyć niestandardowy typ w SQL i skojarzyć ten typ z procedurą przechowywaną. Jeśli kiedykolwiek zmieniłem coś w mojej procedurze składowanej lub schemacie db w dół drogi, musiałbym powtórzyć zarówno procedurę przechowywaną, jak i typ niestandardowy. Chcę uniknąć tej sytuacji. Poza tym przewaga TVP nad XML nie jest przydatna w mojej sytuacji, ponieważ rozmiar mojej tablicy danych nigdy nie przekroczy 1000. Oznacza to, że nie mogę użyć zaproponowanego rozwiązania: Jak wstawić wiele rekordów przy użyciu XML w SQL Server 2008
Również podobna dyskusja tutaj ( UPSERT - czy istnieje lepsza alternatywa dla MERGE lub @@ rowcount? ) Różni się od tego, o co proszę, ponieważ próbuję wstawić wiele wierszy do tabeli.
Miałem nadzieję, że użyję następującego zestawu zapytań, aby wstawić wartości z pliku XML. Ale to nie zadziała. To podejście powinno działać tylko wtedy, gdy dane wejściowe są jednym wierszem.
begin tran
update table with (serializable) set select * from xml_param
where key = @key
if @@rowcount = 0
begin
insert table (key, ...) values (@key,..)
end
commit tran
Kolejną alternatywą jest użycie wyczerpującego JEŚLI ISTNIEJE lub jednej z jego odmian poniższej formy. Ale odrzucam to z powodu nieoptymalnej wydajności:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
Następną opcją było użycie instrukcji Merge, jak opisano tutaj: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Ale potem przeczytałem o problemach z kwerendą scalania tutaj: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . Z tego powodu staram się unikać scalania.
Więc teraz moje pytanie brzmi: czy jest jakaś inna opcja lub lepszy sposób na uzyskanie wielu upsert za pomocą parametru XML w procedurze przechowywanej SQL Server 2008?
Należy pamiętać, że dane w parametrze XML mogą zawierać niektóre rekordy, których nie należy UPSERTED, ponieważ są starsze niż bieżący rekord. W ModifiedDate
tabeli XML i tabeli docelowej znajduje się pole, które należy porównać, aby ustalić, czy rekord powinien zostać zaktualizowany, czy odrzucony.
MERGE
tym, na co zwraca uwagę Bertrand, to w większości przypadki przewagi i nieefektywności, a nie pokazywanie ograniczników - MS nie wydałoby tego, gdyby to było prawdziwe pole minowe. Czy jesteś pewien, że splot, przez który przechodzisz, aby uniknąć, MERGE
nie powoduje więcej potencjalnych błędów niż oszczędza?
MERGE
. Kroki INSERT i UPDATE scalenia są nadal przetwarzane osobno. Główną różnicą w moim podejściu jest zmienna tabeli, która przechowuje zaktualizowane identyfikatory rekordów oraz zapytanie DELETE, które używa tej zmiennej tabeli do usunięcia tych rekordów z tabeli temp przychodzących danych. I przypuszczam, że ŹRÓDŁO mogłoby być bezpośrednio z @ XMLparam.nodes () zamiast zrzucać do tabeli tymczasowej, ale nadal nie jest to wiele dodatkowych rzeczy, które nie musiałyby się martwić, że kiedykolwiek znajdziesz się w jednym z tych skrajnych przypadków; - ).