Usuário com melhor resposta
XQUERY

Pergunta
-
Pessoal,
Preciso fazer um loop na tag <segmento> pois ele pode vir variável, 1 ou 10 por exemplo. Consegui fazer. So que quando coloco esse código para rodar em uma proc que vai receber 1500 XMLs de uma tabela cada um numa linha da tabela esse comando demora muito. Acredito que seja alguma coisa relacionada a esse "Where". Pois quando diminuo os campos, ele vai muito mais rápido, mas preciso de todos os campos. E so consegui fazer dessa forma. Alguem sabe se esse "Where" pode ser substituido por algo parecido e mais rápido ?
declare @venda XML, @Temp2 XML
set @venda='<venda>
<origem>aaa</origem>
<idvenda>11111</idvenda>
<tipoproduto>aaa</tipoproduto>
<clasproduto>N</clasproduto>
<idemissor/>
<dtemissao>01/1/2012</dtemissao>
<idcliente/>
<idoperador>aaa</idoperador>
<idfornecedor>JddJ</idfornecedor>
<formpagtos>
<formpagto>
<tipo>1</tipo>
</formpagto>
</formpagtos>
<centrocustocli/>
<setorcli/>
<solicitante/>
<movimentos>
<aereorodoviario>
<pax>aaaaa</pax>
<tipo>aa</tipo>
<basetarifaria/>
<tarifa>0000</tarifa>
<tarifacheia>000</tarifacheia>
<moeda>BRL</moeda>
<cambio>aaaaa</cambio>
<datacambio>01/01/01</datacambio>
<taxaembarque>1111</taxaembarque>
<taxaservico>1111</taxaservico>
<repassedu>0000</repassedu>
<taxacartaodu>000</taxacartaodu>
<voosugerido>
<tarifasugerida/>
<numvoosugerido/>
<motivosugerido/>
<siglasugerida/>
</voosugerido>
<bilhetes>
<bilhete>
<numero>11111</numero>
</bilhete>
</bilhetes>
<comisrecforvalor>000</comisrecforvalor>
<descpagclivalor>0000</descpagclivalor>
<observacao/>
<numautorizacao/>
</aereorodoviario>
<trechos>
<segmento>
<de>aaa</de>
<para>Aaa</para>
<datasaida>01/01/01</datasaida>
<datachegada>01/01/01</datachegada>
<horasaida>0000</horasaida>
<horachegada>0000</horachegada>
<Voo>1111</Voo>
<classe>a</classe>
<localizador>aaa</localizador>
<status>aaaa</status>
<conexao>a</conexao>
<ciaaerea>aa</ciaaerea>
</segmento>
<segmento>
<de>bbb</de>
<para>bbb</para>
<datasaida>01/01/01</datasaida>
<datachegada>01/01/01</datachegada>
<horasaida>0000</horasaida>
<horachegada>0000</horachegada>
<Voo>111</Voo>
<classe>a</classe>
<localizador>aaa</localizador>
<status>Aaa</status>
<conexao>A</conexao>
<ciaaerea>aa</ciaaerea>
</segmento>
</trechos>
</movimentos>
</venda>'
SET @temp2 = @venda.query('
for $a in /venda/movimentos/trechos/segmento/de,
$b in /venda/movimentos/trechos/segmento/para,
$c in /venda/movimentos/trechos/segmento/datasaida,
$d in /venda/movimentos/trechos/segmento/datachegada,
$e in /venda/movimentos/trechos/segmento/Voo,
$f in /venda/movimentos/trechos/segmento/ciaaerea,
$g in /venda/movimentos/trechos/segmento/localizador,
$h in /venda/movimentos/trechos/segmento/classe,
$i in /venda/movimentos/trechos/segmento/status,
$j in /venda/movimentos/trechos/segmento/conexao
where $a/.. is $b/..
and $a/.. is $c/..
and $a/.. is $d/..
and $a/.. is $e/..
and $a/.. is $f/..
and $a/.. is $g/..
and $a/.. is $h/..
and $a/.. is $i/..
and $a/.. is $j/..
return element detail {attribute de {string($a)},
attribute para {string($b)},
attribute datasaida {string($c)},
attribute datachegada {string($d)},
attribute Voo {string($e)},
attribute ciaaerea {string($f)},
attribute localizador {string($g)},
attribute classe {string($h)},
attribute status {string($i)},
attribute conexao {string($j)}}')
SELECT t.c.value('@de','varchar(10)') as [de],
t.c.value('@para','varchar(10)') as [para],
t.c.value('@ciaaerea','varchar(20)') as [ciaaerea],
t.c.value('@datasaida','varchar(30)') as [datasaida],
t.c.value('@datachegada','varchar(30)') as [datachegada],
t.c.value('@Voo','varchar(20)') as [Voo],
t.c.value('@localizador','varchar(20)') as [localizador],
t.c.value('@classe','varchar(20)') as [classe],
t.c.value('@status','varchar(20)') as [status],
t.c.value('@conexao','varchar(20)') as [conexao]
FROM @temp2.nodes('/detail') as t(c)- Movido Roberson Ferreira _ quarta-feira, 22 de agosto de 2012 02:28 (De:SQL Server - Desenvolvimento Geral)
Respostas
-
Olá Flávio,
Espero que tenhamos conseguido resolver sem o loop.
Caso a solução tenha sido satisfatória, você poderia marcar a resposta ?[ ]s,
Gustavo Maia Aguiar
Blog: http://gustavomaiaaguiar.wordpress.com
Vídeos:http://www.youtube.com/user/gmasqlClassifique as respostas. O seu feedback é imprescindível
- Marcado como Resposta Flavio Climaco sexta-feira, 24 de agosto de 2012 18:50
Todas as Respostas
-
Boa Noite,
Estou vendo que por esse e por sua outra thread, você está utilizando o método query em lugares onde ele não é necessário e nem performático. Veja que o nodes e o value diretamente é muito mais enxuto e eficiente. Coloquei um exemplo a partir de uma coluna e não de uma variável. Espero que ajude
create table #tmp (id int, val xml)
insert into #tmp values (1,'<venda>
<origem>aaa</origem>
<idvenda>11111</idvenda>
<tipoproduto>aaa</tipoproduto>
<clasproduto>N</clasproduto>
<idemissor />
<dtemissao>01/1/2012</dtemissao>
<idcliente />
<idoperador>aaa</idoperador>
<idfornecedor>JddJ</idfornecedor>
<formpagtos>
<formpagto>
<tipo>1</tipo>
</formpagto>
</formpagtos>
<centrocustocli />
<setorcli />
<solicitante />
<movimentos>
<aereorodoviario>
<pax>aaaaa</pax>
<tipo>aa</tipo>
<basetarifaria />
<tarifa>0000</tarifa>
<tarifacheia>000</tarifacheia>
<moeda>BRL</moeda>
<cambio>aaaaa</cambio>
<datacambio>01/01/01</datacambio>
<taxaembarque>1111</taxaembarque>
<taxaservico>1111</taxaservico>
<repassedu>0000</repassedu>
<taxacartaodu>000</taxacartaodu>
<voosugerido>
<tarifasugerida />
<numvoosugerido />
<motivosugerido />
<siglasugerida />
</voosugerido>
<bilhetes>
<bilhete>
<numero>11111</numero>
</bilhete>
</bilhetes>
<comisrecforvalor>000</comisrecforvalor>
<descpagclivalor>0000</descpagclivalor>
<observacao />
<numautorizacao />
</aereorodoviario>
<trechos>
<segmento>
<de>aaa</de>
<para>Aaa</para>
<datasaida>01/01/01</datasaida>
<datachegada>01/01/01</datachegada>
<horasaida>0000</horasaida>
<horachegada>0000</horachegada>
<Voo>1111</Voo>
<classe>a</classe>
<localizador>aaa</localizador>
<status>aaaa</status>
<conexao>a</conexao>
<ciaaerea>aa</ciaaerea>
</segmento>
<segmento>
<de>bbb</de>
<para>bbb</para>
<datasaida>01/01/01</datasaida>
<datachegada>01/01/01</datachegada>
<horasaida>0000</horasaida>
<horachegada>0000</horachegada>
<Voo>111</Voo>
<classe>a</classe>
<localizador>aaa</localizador>
<status>Aaa</status>
<conexao>A</conexao>
<ciaaerea>aa</ciaaerea>
</segmento>
</trechos>
</movimentos>
</venda>')SELECT ID,
t.c.value('(de)[1]','varchar(10)') as [de],
t.c.value('(para)[1]','varchar(10)') as [para],
t.c.value('(ciaaerea)[1]','varchar(20)') as [ciaaerea],
t.c.value('(datasaida)[1]','varchar(30)') as [datasaida],
t.c.value('(datachegada)[1]','varchar(30)') as [datachegada],
t.c.value('(Voo)[1]','varchar(20)') as [Voo],
t.c.value('(localizador)[1]','varchar(20)') as [localizador],
t.c.value('(classe)[1]','varchar(20)') as [classe],
t.c.value('(status)[1]','varchar(20)') as [status],
t.c.value('(conexao)[1]','varchar(20)') as [conexao]
FROM #tmp
cross apply val.nodes('/venda/movimentos/trechos/segmento') t(c)[ ]s,
Gustavo Maia Aguiar
Blog: http://gustavomaiaaguiar.wordpress.com
Vídeos:http://www.youtube.com/user/gmasqlClassifique as respostas. O seu feedback é imprescindível
- Sugerido como Resposta Gustavo Maia Aguiar quarta-feira, 22 de agosto de 2012 03:05
-
Entao caro Gustavo,
É justamente isso que eu não posso fazer, usar fixando [1] ou [2], pois como disse anteriormente, o ,<segmento> nesse caso são 2, mas poderia ser 4 ou 3 ou 10. Preciso entao fazer um loop de qualquer forma. So consegui usando essa estrutura onde o for usa as variaveis $a, $b, $c... o que deixa isso lento é justamente o "Where"... Por isso não posso usar o value e o nodes. Entendeu ?
-
Bom Dia Jacinto,
A menos que eu não tenha compreendido sua dúvida, creio que sua percepção sobre o [1] está equivocada. No seu exemplo há dois segmentos, mas o uso do [1] foi capaz de resolver o problema, pois retornou os dois registros (tanto o nodes quanto a sua XQuery retornaram o mesmo resultado). O [1] de fato é para retornar a primeira ocorrência, mas como a navegação via XPath foi no nó mais baixo, você consegue retornar todas as ocorrências. Ex:
declare @xml xml
set @xml = '
<Ocorrencias>
<Ocorrencia Cod="1">
<Dados>
<Solicitante>João</Solicitante>
<Data>2012-08-20</Data>
</Dados>
</Ocorrencia>
<Ocorrencia Cod="2">
<Dados>
<Solicitante>José</Solicitante>
<Data>2012-08-21</Data>
</Dados>
</Ocorrencia>
<Ocorrencia Cod="3">
<Dados>
<Solicitante>Armando</Solicitante>
<Data>2012-08-22</Data>
</Dados>
</Ocorrencia>
</Ocorrencias>'select
X.x.value('(Solicitante)[1]','varchar(100)')
from @xml.nodes('/Ocorrencias/Ocorrencia/Dados') X(x)Nesse exemplo, existem três ocorrências e tudo é retornado. Se você colocar uma quarta ocorrência, ela também seria retornada. Você conseguiria postar uma situação que você tenha que o nodes não foi capaz de resolver ?
[ ]s,
Gustavo Maia Aguiar
Blog: http://gustavomaiaaguiar.wordpress.com
Vídeos:http://www.youtube.com/user/gmasqlClassifique as respostas. O seu feedback é imprescindível
- Marcado como Resposta Flavio Climaco quarta-feira, 22 de agosto de 2012 16:28
- Não Marcado como Resposta Flavio Climaco quarta-feira, 22 de agosto de 2012 16:28
-
Sim Gustavo realmente cara... Obrigado pela ajuda meu amigo.
- Marcado como Resposta Flavio Climaco quarta-feira, 22 de agosto de 2012 16:27
- Não Marcado como Resposta Flavio Climaco quarta-feira, 22 de agosto de 2012 16:27
-
Jacinto,
Se você precisa retornar as outras Tags do seu XML, basta especificar no comando Select, veja o exemplo:
declare
@xml xml
set @xml = '
<Ocorrencias>
<Ocorrencia Cod="1">
<Dados>
<Solicitante>Joo</Solicitante>
<Data>2012-08-20</Data>
</Dados>
</Ocorrencia>
<Ocorrencia Cod="2">
<Dados>
<Solicitante>Jos</Solicitante>
<Data>2012-08-21</Data>
</Dados>
</Ocorrencia>
<Ocorrencia Cod="3">
<Dados>
<Solicitante>Armando</Solicitante>
<Data>2012-08-22</Data>
</Dados>
</Ocorrencia>
</Ocorrencias>'
select
X.x.value('(Solicitante)[1]','varchar(100)'),
X.x.value('(Data)[1]','varchar(10)')
from @xml.nodes('/Ocorrencias/Ocorrencia/Dados') X(x)
Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]
-
Olá Flávio,
Espero que tenhamos conseguido resolver sem o loop.
Caso a solução tenha sido satisfatória, você poderia marcar a resposta ?[ ]s,
Gustavo Maia Aguiar
Blog: http://gustavomaiaaguiar.wordpress.com
Vídeos:http://www.youtube.com/user/gmasqlClassifique as respostas. O seu feedback é imprescindível
- Marcado como Resposta Flavio Climaco sexta-feira, 24 de agosto de 2012 18:50