Modifica XML in SQL Server per aggiungere un nodo radice
-
05-07-2019 - |
Domanda
Per dare prima qualche informazione su questo problema, sto riscrivendo un po 'di codice che attualmente scorre attraverso un po' di xml, facendo un inserimento in una tabella alla fine di ogni ciclo - sostituendolo con un singolo sp che accetta un parametro xml e fa il inserire in una sola volta, "distruggendo" l'xml in una tabella.
Lo shred principale è stato eseguito correttamente, ma attualmente una delle colonne viene utilizzata per memorizzare l'intero nodo. Sono stato in grado di elaborare la query necessaria per questo (quasi), ma manca la parte radice del nodo. Sono giunto alla conclusione che la mia query è la migliore possibile, e sto cercando un modo per fare un'istruzione di aggiornamento per riportare il nodo root lì dentro.
Quindi il mio XML è nella forma;
<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>
Quindi la distruzione di base mette il valore da node1 a column1, node2 in column2 ecc. L'istruzione insert ha un aspetto simile;
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)
L'XML che finisce in wholenodecolumn è della forma;
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
ma ho bisogno che sia nella forma
<Item><node1>...</node1><node2>..<node2>.....<noden>...<noden></Item>
Esiste un codice esistente (in gran parte) che dipende dal fatto che il codice XML in questa colonna abbia la forma corretta.
Quindi qualcuno può forse vedere come modificare doc.col.query('*')
per ottenere il risultato desiderato?
Comunque, ho rinunciato a modificare la query e ho cercato di pensare ad altri modi per ottenere il risultato finale. Quello che sto guardando ora è un aggiornamento dopo l'inserimento, qualcosa del genere;
update mytable set wholenodecolumn.modify('insert <Item> as first before * ')
Se potessi farlo insieme a
.modify('insert </Item> as last after * ')
andrebbe bene, ma fare 1 alla volta non è un'opzione poiché l'XML non è quindi valido
XQuery [mytable.wholenodecolumn.modify()]: Expected end tag 'Item'
e facendo entrambe le cose insieme non so se sia possibile, ma ho provato varie sintassi e non riesco a lavorare.
Anche altri approcci al problema hanno ricevuto con gratitudine
Soluzione 2
Rispondi alla mia domanda qui! - questo fa seguito ai commenti a una delle altre tentate risposte in cui ho detto:
Attualmente sto esaminando FLWOR Xquery costruisce nella query.
col.query('for $item in * return <Item> {$item} </item>')
è quasi lì, ma mette in giro ogni nodo, piuttosto che intorno a tutto il nodi
Ero quasi lì con la sintassi, una piccola modifica mi ha dato ciò di cui avevo bisogno;
doc.col.query('<Item> { for $item in * return $item } </item>'
Grazie a tutti quelli che mi hanno aiutato. Ho ulteriori problemi correlati ora, ma posterò come domande separate
Altri suggerimenti
Credo che sia possibile specificare il nome del nodo principale utilizzando la clausola FOR.
Ad esempio:
select top 1 *
from HumanResources.Department
for XML AUTO, ROOT('RootNodeName')
Dai un'occhiata ai libri online per maggiori dettagli:
Non potresti semplicemente aggiungere '' / '' come testi fissi nella tua selezione? Qualcosa del tipo:
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