J'ai une XML
colonne qui contient des données avec une structure similaire:
<Root>
<Elements>
<Element Code="1" Value="aaa"></Element>
<Element Code="2" Value="bbb"></Element>
<Element Code="3" Value="ccc"></Element>
</Elements>
</Root>
Comment puis-je modifier les données à l'aide de SQL Server pour changer chaque Value
attribut en un élément?
<Root>
<Elements>
<Element Code="1">
<Value>aaa</Value>
</Element>
<Element Code="2">
<Value>bbb</Value>
</Element>
<Element Code="3">
<Value>ccc</Value>
</Element>
</Elements>
</Root>
Mise à jour:
Mon XML ressemble plus à ceci:
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
<Element Code="4" Value="" ExtraData="extra" />
<Element Code="5" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>
Je voudrais seulement déplacer l' Value
attribut et conserver tous les autres attributs et éléments.
sql-server
xml
xquery
Wojteq
la source
la source
<Value>
éléments pour chacun<Element>
. Si ce n'est pas le cas, le déplacement de l'attribut vers un élément rend simplement XML plus gonflé et peut-être moins efficace.<Value>
élément ou à la place de celui-ci.Réponses:
Vous pouvez détruire le XML et le reconstruire à nouveau à l'aide de XQuery.
Résultat:
Si
Elements
n'est pas le premier élément sousRoot
la requête doit être modifié pour ajouter tous les éléments avantElements
premier et tous les éléments aprèsElements
après.la source
Vous pouvez également utiliser les méthodes du type de données XML (par exemple, modifier ) et certains XQuery pour modifier le xml, par exemple
Cette méthode n'a pas tendance à bien évoluer sur de gros morceaux de XML, mais pourrait vous convenir mieux qu'un remplacement en gros du XML.
Vous pouvez également facilement adapter cette méthode si votre XML est stocké dans une table. Encore une fois, par expérience, je ne recommanderais pas d'exécuter une seule mise à jour sur une table d'un million de lignes. Si votre table est volumineuse, envisagez d'exécuter un curseur dessus ou de regrouper les mises à jour. Voici la technique:
la source
MISE À JOUR:
J'ai mis à jour le code, ainsi que le XML d'entrée et de sortie dans l'exemple de requête ci-dessous pour refléter la dernière exigence, indiquée dans un commentaire sur la bonne réponse de @ Mikael , qui est:
Bien qu'une seule expression puisse correspondre correctement à cette nouvelle variation, il ne semble pas y avoir de moyen d'omettre l'
<Value/>
élément vide en une seule passe car la logique conditionnelle n'est pas autorisée dans la chaîne de remplacement. J'ai donc adapté cela pour être une modification en 2 parties: une passe pour obtenir les@Value
attributs non vides et une passe pour obtenir les@Value
attributs vides . Il n'était pas nécessaire de gérer<Element>
l'@Value
attribut manquant car le souhait est de ne pas avoir l'<Value>
élément de toute façon.Une option consiste à traiter le XML comme une chaîne régulière et à le transformer en fonction d'un modèle. Ceci est facilement accompli en utilisant des expressions régulières (en particulier la fonction "Remplacer") qui peuvent être mises à disposition via le code SQLCLR.
L'exemple ci-dessous utilise l' UDF scalaire RegEx_Replace de la bibliothèque SQL # (dont je suis l'auteur, mais cette fonction RegEx est disponible dans la version gratuite, ainsi que de nombreuses autres):
Les
PRINT
instructions sont là juste pour faciliter la comparaison côte à côte dans l'onglet "Messages". La sortie résultante est (j'ai légèrement modifié le XML d'origine pour qu'il soit très clair que seules les parties souhaitées ont été touchées et rien d'autre):Si vous souhaitez mettre à jour un champ dans une table, vous pouvez adapter ce qui précède comme suit:
la source
Il existe probablement de meilleures façons de le faire en dehors de SQL Server. Cependant, voici une façon de procéder.
Le CTE xml transforme votre variable xml en table.
La sélection principale transforme ensuite le CTE en XML.
Cela peut également être fait en utilisant
For XML Explicit
.la source