Sto cercando di aggiornare una tabella con una matrice di valori. Ogni elemento nella matrice contiene informazioni che corrispondono a una riga in una tabella nel database di SQL Server. Se la riga esiste già nella tabella, aggiorniamo quella riga con le informazioni nell'array specificato. Altrimenti, inseriamo una nuova riga nella tabella. Ho sostanzialmente descritto upsert.
Ora sto provando a raggiungere questo obiettivo in una procedura memorizzata che accetta un parametro XML. Il motivo per cui sto usando XML e non un parametro con valori di tabella è perché, facendo quest'ultimo, dovrò creare un tipo personalizzato in SQL e associare questo tipo alla procedura memorizzata. Se avessi mai cambiato qualcosa nella mia procedura memorizzata o nel mio schema db lungo la strada, avrei dovuto ripetere sia la procedura memorizzata che il tipo personalizzato. Voglio evitare questa situazione. Inoltre, la superiorità che TVP ha su XML non è utile per la mia situazione perché, la dimensione della mia matrice di dati non supererà mai 1000. Ciò significa che non posso usare la soluzione proposta qui: Come inserire più record usando XML in SQL Server 2008
Inoltre, una discussione simile qui ( UPSERT - Esiste un'alternativa migliore a MERGE o @@ rowcount? ) È diversa da quella che sto chiedendo perché, sto provando a caricare più righe su una tabella.
Speravo che avrei semplicemente usato il seguente set di query per confermare i valori dall'xml. Ma questo non funzionerà. Questo approccio dovrebbe funzionare solo quando l'input è una singola riga.
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
La prossima alternativa è quella di utilizzare un ESISTENTE esaustivo o una delle sue varianti nella forma seguente. Ma, lo rifiuto per motivi di efficienza non ottimale:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
L'opzione successiva è stata l'utilizzo dell'istruzione Merge come descritto qui: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Ma poi ho letto dei problemi con la query Unisci qui: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . Per questo motivo, sto cercando di evitare Merge.
Quindi, ora la mia domanda è: c'è qualche altra opzione o un modo migliore per ottenere più upsert usando il parametro XML nella procedura memorizzata di SQL Server 2008?
Si noti che i dati nel parametro XML possono contenere alcuni record che non devono essere UPSERTed perché più vecchi del record corrente. Esiste un ModifiedDate
campo sia nell'XML che nella tabella di destinazione che deve essere confrontato per determinare se il record deve essere aggiornato o scartato.
MERGE
che Bertrand evidenzia sono principalmente casi limite e inefficienze, non mostrano ostacoli: la MS non lo avrebbe rilasciato se fosse stato un vero campo minato. Sei sicuro che le convoluzioni che stai attraversando per evitare MERGE
non stanno creando più potenziali errori di quelli che stanno salvando?
MERGE
. Le fasi INSERT e UPDATE di MERGE vengono comunque elaborate separatamente. La differenza principale nel mio approccio è la variabile di tabella che contiene gli ID record aggiornati e la query DELETE che utilizza quella variabile di tabella per rimuovere quei record dalla tabella temporanea dei dati in arrivo. E suppongo che SOURCE possa essere diretto da @ XMLparam.nodes () invece di scaricare su una tabella temporanea, ma non è un sacco di roba extra di cui non doversi preoccupare di ritrovarsi in uno di quei casi limite; - ).