Я пытаюсь обновить таблицу с массивом значений. Каждый элемент в массиве содержит информацию, которая соответствует строке в таблице в базе данных SQL Server. Если строка уже существует в таблице, мы обновляем эту строку информацией из данного массива. Иначе, мы вставляем новую строку в таблицу. Я в основном описал upsert.
Теперь я пытаюсь добиться этого в хранимой процедуре, которая принимает параметр XML. Причина, по которой я использую XML, а не параметр с табличным значением, заключается в том, что в последнем случае мне придется создавать пользовательский тип в SQL и связывать этот тип с хранимой процедурой. Если бы я когда-нибудь что-то изменил в своей хранимой процедуре или в моей схеме БД, мне пришлось бы повторить как хранимую процедуру, так и пользовательский тип. Я хочу избежать этой ситуации. Кроме того, преимущество, которое TVP имеет над XML, не полезно для моей ситуации, потому что размер моего массива данных никогда не будет превышать 1000. Это означает, что я не могу использовать предложенное здесь решение: Как вставить несколько записей с использованием XML в SQL Server 2008
Кроме того, подобное обсуждение здесь ( UPSERT - есть ли лучшая альтернатива MERGE или @@ rowcount? ) Отличается от того, что я спрашиваю, потому что я пытаюсь добавить несколько строк в таблицу.
Я надеялся, что просто воспользуюсь следующим набором запросов для сохранения значений из xml. Но это не сработает. Этот подход просто должен работать, когда вход представляет собой одну строку.
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
Следующей альтернативой является использование исчерпывающего IF EXISTS или одного из его вариантов следующей формы. Но я отвергаю это из-за неоптимальной эффективности:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
Следующим вариантом было использование оператора Merge, как описано здесь: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Но затем я прочитал о проблемах с запросом Merge здесь: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . По этой причине я пытаюсь избежать слияния.
Итак, теперь мой вопрос: есть ли какой-либо другой вариант или лучший способ добиться множественного восстановления с использованием параметра XML в хранимой процедуре SQL Server 2008?
Обратите внимание, что данные в параметре XML могут содержать некоторые записи, которые не должны быть UPSERTed из-за того, что они старше, чем текущая запись. В ModifiedDate
таблице XML и в таблице назначения есть поле, которое необходимо сравнить, чтобы определить, должна ли запись быть обновлена или отброшена.
MERGE
которые указывает Бертран, - это, в основном, крайние случаи и неэффективность, а не пробки - MS не выпустила бы это, если бы это было настоящее минное поле. Вы уверены, что извилины, которые вы проходите, чтобы избежать MERGE
, не создают больше потенциальных ошибок, чем они сохраняют?
MERGE
. Шаги INSERT и UPDATE в MERGE по-прежнему обрабатываются отдельно. Основным отличием в моем подходе является переменная таблицы, которая содержит обновленные идентификаторы записей, и запрос DELETE, который использует эту переменную таблицы для удаления этих записей из временной таблицы входящих данных. И я полагаю, что SOURCE может быть прямым из @ XMLparam.nodes () вместо дампа во временную таблицу, но, тем не менее, это не так уж много лишних вещей, чтобы не беспокоиться о том, что вы окажетесь в одном из этих крайних случаев; ).