Modifier XML dans SQL Server pour ajouter un nœud racine
-
05-07-2019 - |
Question
Pour commencer par expliquer ce problème, je suis en train de réécrire du code qui parcourt actuellement du XML, en effectuant une insertion dans une table à la fin de chaque boucle - en le remplaçant par un seul sp qui prend un paramètre xml et effectue les opérations suivantes. insérer en une fois, 'déchiqueter' le code XML dans un tableau.
La destruction principale a été effectuée avec succès, mais l’une des colonnes est actuellement utilisée pour stocker le nœud entier. J'ai pu résoudre (presque) la requête nécessaire pour cela, mais il manque la partie racine du nœud. Je suis parvenu à la conclusion que ma requête était aussi bonne que possible, et je cherche un moyen de faire ensuite une déclaration de mise à jour pour obtenir le nœud racine à l'intérieur.
Donc, mon XML est de la forme;
<xml>
<Items>
<Item>
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
<Item>
<Item>
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
<Item>
<Item>
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
<Item>
......
<Items>
</xml>
Ainsi, le déchiquetage de base place la valeur de node1 dans column1, node2 dans column2, etc. L’instruction insert ressemble à quelque chose comme:
INSERT INTO mytable col1, col2,...etc.....,wholenodecolumn
Select
doc.col.value('node1[1]', 'int') column1,
doc.col.value('node2[1]', 'varchar(50)') column2,
....etc......,
doc.col.query('*')--this is the query for getting the whole node
FROM @xml.nodes('//Items/Item') doc(col)
Le code XML qui se termine dans wholenodecolumn est de la forme;
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
mais j'en ai besoin pour être de la forme
<Item><node1>...</node1><node2>..<node2>.....<noden>...<noden></Item>
Il y a du code existant (en grande partie) qui dépend du xml dans cette colonne étant de la forme correcte.
Alors, quelqu'un peut-il voir comment modifier doc.col.query('*')
pour obtenir le résultat souhaité?
Quoi qu'il en soit, j’ai renoncé à modifier la requête et j’ai essayé de trouver d’autres moyens d’atteindre le résultat final. Ce que je suis en train de regarder est une mise à jour après l’insertion, quelque chose comme;
update mytable set wholenodecolumn.modify('insert <Item> as first before * ')
Si je pouvais le faire avec
.modify('insert </Item> as last after * ')
ce serait bien, mais faire 1 à la fois n'est pas une option car le XML est alors invalide
XQuery [mytable.wholenodecolumn.modify()]: Expected end tag 'Item'
et faire les deux ensemble je ne sais pas si c'est possible, mais j'ai essayé diverses syntaxes et je ne peux pas me rendre au travail.
Toute autre approche du problème a également été reçue avec gratitude
La solution 2
Répondre à ma propre question ici! - ceci découle des commentaires de l'une des autres tentatives de réponse où j'ai dit:
Je suis actuellement à la recherche de FLWOR Constructions Xquery dans la requête.
col.query('for $item in * return <Item> {$item} </item>')
est presque là, mais met autour chaque nœud, plutôt que autour de tous les nœuds
J'y étais presque avec la syntaxe, un petit ajustement m'a donné ce dont j'avais besoin;
doc.col.query('<Item> { for $item in * return $item } </item>'
Merci à tous ceux qui ont aidé. J'ai d'autres problèmes connexes à présent, mais je posterai des questions séparées
Autres conseils
Je pense que vous pouvez spécifier le nom du nœud racine à l'aide de la clause FOR.
Par exemple:
select top 1 *
from HumanResources.Department
for XML AUTO, ROOT('RootNodeName')
Jetez un coup d'œil aux livres en ligne pour plus de détails:
Ne pourriez-vous pas simplement ajouter le "/" aux textes fixes dans votre sélection? Quelque chose comme:
Select
'<Item>',
doc.col.value('node1[1]', 'int') column1,
doc.col.value('node2[1]', 'varchar(50)') column2,
....etc......,
doc.col.query('*'),
'</Item>' --this is the query for getting the whole node
FROM @xml.nodes('//Items/Item') doc(col)
Marc