Preciso integrar um arquivo XML diário ao meu sistema.
O arquivo XML tem um esquema semelhante a este:
create table txml(id int identity, data xml);
insert into txml (data) values ('
<order>
<trans DTrans="20170102" HTrans="10:52"></trans>
<head Id="552665566"></head>
<lin headId="552665566">
<dLin Id="00001" CoArt="1111111" CoArtCust="05220001" NameArt="Product1" dateVal="20161115" />
<acum DCalAcm="20170101" DIniAcm="20161115"><qtyAcm Qty="1101163.00" /></acum>
<lastOrd Id="95767" QtyLastOrd="12000.00" DLastOrd="20170101" />
<pLin LType="4"><uni Qty="24000.00"/><dIni Date="20170104"/><dEnd Date="20170108"/></pLin>
<pLin LType="4"><uni Qty="20000.00"/><dIni Date="20170109"/><dEnd Date="20170112"/></pLin>
<pLin LType="4"><uni Qty="24000.00"/><dIni Date="20170113"/><dEnd Date="20170116"/></pLin>
</lin>
<lin headId="552665566">
<dLin Id="00002" CoArt="2222222" CoArtCust="05269958" NameArt="Product2" dateVal="20161101" />
<acum DCalAcm="20170101" DIniAcm="20161101"><qtyAcm Qty="552652.00" /></acum>
<lastOrd Id="49956" QtyLastOrd="5000.00" DLastOrd="20170101" />
<pLin LType="4"><uni Qty="2200.00"/><dIni Date="20170104"/><dEnd Date="20170108"/></pLin>
<pLin LType="4"><uni Qty="3000.00"/><dIni Date="20170109"/><dEnd Date="20170116"/></pLin>
</lin>
</order>');
Como você pode ver para cada <lin>
seção, você pode encontrar um número desconhecido de <pLin>
linhas. Até agora estou fazendo este trabalho usando C# e um aplicativo de console .Net, mas gostaria de fazê-lo usando SQL.
Até agora, posso obter um conjunto de linhas de <lin>
tags usando a próxima consulta:
SELECT T2.lin.value('(./dLin/@Id)[1]', 'int') Id,
T2.lin.value('(./dLin/@CoArt)[1]', 'varchar(20)') CoArt,
T2.lin.value('(./dLin/@CoArtCust)[1]', 'varchar(20)') CoArtCust,
T2.lin.value('(./lastOrd/@Id)[1]', 'varchar(20)') lastOrderId,
T2.lin.value('(./lastOrd/@QtyLastOrd)[1]', 'decimal(18,2)') QtyLastOrd
FROM txml
CROSS APPLY data.nodes('/order/lin') as T2(lin);
Isso produz o próximo resultado:
Id | CoArt | CoArtCust | lastOrderId | QtyLastOrd
-: | :------ | :-------- | :---------- | :---------
1 | 1111111 | 05220001 | 95767 | 12000.00
2 | 2222222 | 05269958 | 49956 | 5000.00
Mas devo adicionar linhas aninhadas correspondentes a <pLin>
tags e produzir o próximo resultado:
Id | CoArt | CoArtCust | lastOrderId | QtyLastOrd | DIni | DEnd | NextQty
-: | :------ | :-------- | :---------- | :--------- | ---------- | ---------- | ---------
1 | 1111111 | 05220001 | 95767 | 12000.00 | 04/01/2017 | 08/01/2017 | 24000.00
1 | 1111111 | 05220001 | 95767 | 12000.00 | 09/01/2017 | 12/01/2017 | 20000.00
1 | 1111111 | 05220001 | 95767 | 12000.00 | 13/01/2017 | 16/01/2017 | 24000.00
2 | 2222222 | 05269958 | 49956 | 5000.00 | 04/01/2017 | 08/01/2017 | 2200.00
2 | 2222222 | 05269958 | 49956 | 5000.00 | 09/01/2017 | 16/01/2017 | 3000.00
Eu configurei um dbfiddle aqui
Você pode adicionar um adicional
CROSS APPLY
para dividir as linhas da maneira que desejar:Eu tive que adivinhar o tipo de dados para DIni, correto conforme necessário.