Modifique o XML no SQL Server para adicionar um nó raiz
-
05-07-2019 - |
Pergunta
Para dar alguns antecedentes a esse problema primeiro, estou reescrevendo algum código que atualmente percorre algum XML, fazendo uma inserção em uma tabela no final de cada loop - substituindo por um único SP que pega um parâmetro XML e faz a inserção em um Vá, 'rastejando' o XML em uma mesa.
O fragmento principal foi realizado com sucesso, mas atualmente uma das colunas é usada para armazenar todo o nó. Consegui descobrir a consulta necessária para isso (quase), mas perde a parte raiz do nó. Cheguei à conclusão de que minha consulta é o melhor possível, e estou procurando uma maneira de fazer uma instrução de atualização para obter o nó raiz de volta lá.
Então, meu XML é da 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>
Portanto, a trituração básica coloca o valor de Node1 na coluna1, node2 na coluna e etc. A instrução Insert se parece com algo;
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)
O XML que acaba em Wholenodecolumn é da forma;
<node1>...</node1><node2>..<node2>.....<noden>...<noden>
Mas eu preciso que seja do formulário
<Item><node1>...</node1><node2>..<node2>.....<noden>...<noden></Item>
Existe um código existente (muito disso) que depende do XML nesta coluna estar da forma correta.
Então, alguém pode ver como modificar o doc.col.query('*')
Para obter o resultado desejado?
De qualquer forma, desisti de modificar a consulta e tentei pensar em outras maneiras de realizar o resultado final. O que estou vendo agora é uma atualização após a inserção- algo como;
update mytable set wholenodecolumn.modify('insert <Item> as first before * ')
Se eu pudesse fazer isso junto com
.modify('insert </Item> as last after * ')
Isso seria bom, mas fazer 1 de cada vez não é uma opção, pois o XML é inválido
XQuery [mytable.wholenodecolumn.modify()]: Expected end tag 'Item'
E fazendo os dois juntos, não sei se é possível, mas tentei várias sintaxe e não consigo trabalhar.
Quaisquer outras abordagens para o problema também recebidas com gratidão
Solução 2
Respondendo minha própria pergunta aqui! - Isso segue os comentários para um das outras respostas tentadas onde eu disse:
Atualmente, estou procurando construções da Flwor XQuery na consulta.
col.query('for $item in * return <Item> {$item} </item>')
está quase lá, mas coloca em torno de cada nó, em vez de todos os nós
Eu estava quase lá com a sintaxe, um pequeno ajuste me deu o que eu precisava;
doc.col.query('<Item> { for $item in * return $item } </item>'
Obrigado a todos que ajudaram. Eu tenho mais problemas relacionados agora, mas vou postar como perguntas separadas
Outras dicas
Eu acredito que você pode especificar o nome do nó raiz usando a cláusula for.
Por exemplo:
select top 1 *
from HumanResources.Department
for XML AUTO, ROOT('RootNodeName')
Veja os livros online para obter mais detalhes:
Você não poderia simplesmente adicionar o '' '' como textos fixos em sua seleção? Algo como:
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