Estou tentando atualizar uma tabela com uma matriz de valores. Cada item da matriz contém informações que correspondem a uma linha em uma tabela no banco de dados do SQL Server. Se a linha já existir na tabela, atualizamos essa linha com as informações na matriz especificada. Senão, inserimos uma nova linha na tabela. Eu descrevi basicamente upsert.
Agora, estou tentando fazer isso em um procedimento armazenado que usa um parâmetro XML. O motivo pelo qual estou usando XML e não o parâmetro com valor de tabela é porque, ao fazer isso, terei que criar um tipo personalizado no SQL e associá-lo ao procedimento armazenado. Se alguma vez eu alterasse algo no meu procedimento armazenado ou no meu esquema db no futuro, precisaria refazer o procedimento armazenado e o tipo personalizado. Eu quero evitar essa situação. Além disso, a superioridade que o TVP possui sobre XML não é útil para minha situação, porque o tamanho do meu array de dados nunca excederá 1000. Isso significa que não posso usar a solução proposta aqui: Como inserir vários registros usando XML no SQL Server 2008
Além disso, uma discussão semelhante aqui ( UPSERT - Existe uma alternativa melhor para MERGE ou @@ rowcount? ) É diferente do que estou perguntando, porque estou tentando alterar várias linhas para uma tabela.
Eu esperava que simplesmente usasse o seguinte conjunto de consultas para alterar os valores do xml. Mas isso não vai funcionar. Essa abordagem deve funcionar quando a entrada for uma única linha.
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
A próxima alternativa é usar um IF EXISTENTE exaustivo ou uma de suas variações da seguinte forma. Mas, rejeito isso por ter uma eficiência abaixo do ideal:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
A próxima opção foi usar a instrução Merge, conforme descrito aqui: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Mas, então, li sobre problemas com a consulta Merge aqui: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . Por esse motivo, estou tentando evitar a mesclagem.
Então, agora minha pergunta é: existe alguma outra opção ou uma maneira melhor de obter vários upsert usando o parâmetro XML no procedimento armazenado do SQL Server 2008?
Observe que os dados no parâmetro XML podem conter alguns registros que não devem ser UPSERTed devido a serem mais antigos que o registro atual. Há um ModifiedDate
campo no XML e na tabela de destino que precisa ser comparado para determinar se o registro deve ser atualizado ou descartado.
MERGE
quais Bertrand aponta são principalmente casos extremos e ineficiências, não mostram rolhas - a MS não a teria liberado se fosse um campo minado real. Tem certeza de que as convulsões que você está passando para evitar MERGE
não estão criando mais erros em potencial do que estão salvando?
MERGE
. As etapas INSERT e UPDATE do MERGE ainda são processadas separadamente. A principal diferença em minha abordagem é a variável de tabela que contém os IDs de registro atualizados e a consulta DELETE que usa essa variável de tabela para remover esses registros da tabela temporária dos dados recebidos. E suponho que a SOURCE possa ser direta de @ XMLparam.nodes () em vez de despejar em uma tabela temporária, mas ainda assim, isso não é muita coisa extra para você não ter que se preocupar em encontrar-se em um desses casos extremos; - )