J'essaie de mettre à jour une table avec un tableau de valeurs. Chaque élément du tableau contient des informations qui correspondent à une ligne d'une table dans la base de données SQL Server. Si la ligne existe déjà dans la table, nous mettons à jour cette ligne avec les informations dans le tableau donné. Sinon, nous insérons une nouvelle ligne dans le tableau. J'ai essentiellement décrit upsert.
Maintenant, j'essaie d'y parvenir dans une procédure stockée qui prend un paramètre XML. La raison pour laquelle j'utilise XML et non un paramètre table est que, ce faisant, je devrai créer un type personnalisé en SQL et associer ce type à la procédure stockée. Si jamais je modifiais quelque chose dans ma procédure stockée ou mon schéma db sur la route, je devrais refaire à la fois la procédure stockée et le type personnalisé. Je veux éviter cette situation. En outre, la supériorité de TVP sur XML n'est pas utile dans ma situation car, la taille de mon tableau de données ne dépassera jamais 1000. Cela signifie que je ne peux pas utiliser la solution proposée ici: Comment insérer plusieurs enregistrements à l'aide de XML dans SQL Server 2008
En outre, une discussion similaire ici ( UPSERT - Existe-t-il une meilleure alternative à MERGE ou @@ rowcount? ) Est différente de ce que je demande parce que j'essaie d'insérer plusieurs lignes dans une table.
J'espérais que j'utiliserais simplement l'ensemble de requêtes suivant pour inverser les valeurs du xml. Mais cela ne fonctionnera pas. Cette approche est censée fonctionner uniquement lorsque l'entrée est une seule ligne.
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 prochaine alternative consiste à utiliser un IF EXISTS exhaustif ou l'une de ses variantes de la forme suivante. Mais, je rejette cela au motif d'être d'une efficacité sous-optimale:
IF (SELECT COUNT ... ) > 0
UPDATE
ELSE
INSERT
L'option suivante utilisait l'instruction Merge comme décrit ici: http://www.databasejournal.com/features/mssql/using-the-merge-statement-to-perform-an-upsert.html . Mais, j'ai lu des informations sur les problèmes de fusion ici: http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ . Pour cette raison, j'essaie d'éviter la fusion.
Donc, maintenant ma question est: existe-t-il une autre option ou une meilleure façon d'obtenir plusieurs upsert en utilisant le paramètre XML dans la procédure stockée SQL Server 2008?
Veuillez noter que les données du paramètre XML peuvent contenir certains enregistrements qui ne doivent pas être supprimés en raison de leur ancienneté par rapport à l'enregistrement actuel. Il existe un ModifiedDate
champ dans le XML et dans la table de destination qui doit être comparé afin de déterminer si l'enregistrement doit être mis à jour ou supprimé.
MERGE
lesquels Bertrand souligne sont principalement des cas marginaux et des inefficacités, pas des bouchons - MS ne l'aurait pas libéré s'il s'agissait d'un véritable champ de mines. Êtes-vous sûr que les circonvolutions que vous devez éviter MERGE
ne créent pas plus d'erreurs potentielles qu'elles n'en économisent?
MERGE
. Les étapes INSERT et UPDATE de MERGE sont toujours traitées séparément. La principale différence dans mon approche est la variable de table qui contient les ID d'enregistrement mis à jour et la requête DELETE qui utilise cette variable de table pour supprimer ces enregistrements de la table temporaire des données entrantes. Et je suppose que la SOURCE pourrait être directement de @ XMLparam.nodes () au lieu de se déverser dans une table temporaire, mais ce n'est pas beaucoup de choses supplémentaires pour ne pas avoir à vous soucier de vous retrouver dans l'un de ces cas extrêmes; - ).