none
Xquery RRS feed

  • Pergunta

  • Boa Tarde

     

    Caros

     

    Estou com uma duvida com relação ao uso de métodos do Xquery para resolver a seguinte questão.Tenho uma tabela com duas colunas do tipo xml, em cada xml armazenado em ambas as colunas existe um xml com n nós de nome "row" (obtidos com a clausula "FOR XML" do SQL Server), ambos os conteudos das duas colunas tem o mesmo numero de nós do tipo "row", e há entre eles uma colunna de ligação (Chave Primaria), ou seja, gostaria de um comando que me retorne uma linha para cada nó do xml, mando abaixo alguns exemplos.

     

    Esse é o valor de um dos campos.

    <row>
     <Coluna1>2</Coluna1>
     <Coluna2>2</Coluna2>
     <rowguid>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</rowguid>
    </row>
    <row>
     <Coluna1>1</Coluna1>
     <Coluna2>1</Coluna2>
     <rowguid>7163F849-40CA-4F3E-80B3-3955767EC8B3</rowguid>
    </row>
    

    E esse é o valor do outro

     

    <row>
     <Coluna1>4</Coluna1>
     <Coluna2>4</Coluna2>
     <rowguid>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</rowguid>
    </row>
    <row>
     <Coluna1>5</Coluna1>
     <Coluna2>5</Coluna2>
     <rowguid>7163F849-40CA-4F3E-80B3-3955767EC8B3</rowguid>
    </row>
    

    Lembrando, esses conteudos estão em uma mesma linha da tabela, porém em campos diferentes, preciso de um select que retorne duas linhas e duas colunas do tipo Xml , onde a ligação entre as duas colunas é o valor do nó rowguid.

     

    Alguem poderia me ajudar ?

     

    Sem mais

     

    Victor Perez

     

     

     

    terça-feira, 21 de setembro de 2010 20:05

Respostas

  • Junior

     

    Do seu jeito, por algum motivo que eu não sei qual não funciona, pois ele me traz dois nós por Linha, porém, consegui de uma outra forma, relacionar os nós de ambos os Conteudos Xml, porém de uma maneira estranha que eu nem sei como funciona, de uma olhada e veja se tem alguma maneira de melhorar.

     

    Declare @Inserted As Xml = '<row><Coluna1>5</Coluna1><Coluna2>9</Coluna2><ROWGUID>0C8FD950-F360-41DD-8967-27946609A1F6</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>7163F849-40CA-4F3E-80B3-3955767EC8B3</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>963B4DA5-2DC0-43C7-87EB-72F41EA42491</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>1781C061-DB69-493C-AC74-98DDC3AFBEE6</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>CE7B07E2-8CC8-4156-8612-DF8659B7AE20</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>72976C1A-4AFF-41F0-BD1F-F7E952CAEDDB</ROWGUID></row>'
    Declare @Deleted As Xml = '<row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>0C8FD950-F360-41DD-8967-27946609A1F6</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>7163F849-40CA-4F3E-80B3-3955767EC8B3</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>963B4DA5-2DC0-43C7-87EB-72F41EA42491</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>1781C061-DB69-493C-AC74-98DDC3AFBEE6</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>CE7B07E2-8CC8-4156-8612-DF8659B7AE20</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>72976C1A-4AFF-41F0-BD1F-F7E952CAEDDB</ROWGUID></row>'
    
    
    Select
    	 @Deleted.query('(/row)[sql:column("Id")]') As Deleted,
    	 @Inserted.query('(/row)[sql:column("Id")]') As Inserted
    From
    (
    Select
    	Row_Number() Over(Order By Isnull(I.xml.value('(ROWGUID)[1]', 'varchar(40)'), D.xml.value('(ROWGUID)[1]', 'varchar(40)'))) As Id
    From
    	@Inserted.nodes('/row') As I(xml)
    	Full Outer Join @Deleted.nodes('/row') As D(xml)
    	On I.xml.value('(ROWGUID)[1]', 'varchar(40)') = D.xml.value('(ROWGUID)[1]', 'varchar(40)')
    )A
    

    Mesmo assim agradeço pela Ajuda.

     

    Sem mais

     

    Victor Perez

     

     

    • Marcado como Resposta VictorPerez quarta-feira, 22 de setembro de 2010 20:28
    quarta-feira, 22 de setembro de 2010 20:28

Todas as Respostas

  • Bom dia

     

     

    Segue abaixo o meu progresso.

    Declare @Inserted As Xml = '<row>
     <Coluna1>2</Coluna1>
     <Coluna2>2</Coluna2>
     <ROWGUID>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</ROWGUID>
    </row>
    <row>
     <Coluna1>1</Coluna1>
     <Coluna2>1</Coluna2>
     <ROWGUID>7163F849-40CA-4F3E-80B3-3955767EC8B3</ROWGUID>
    </row>'
    
    Declare @Deleted As Xml = @Inserted
    
    
    Select 
    	@Deleted.query('<row ROWGUID = "{sql:column("Id")}"/>') As Teste
    From
    (
    Select
    	Isnull(I.xml.value('(ROWGUID)[1]', 'varchar(40)'), D.xml.value('(ROWGUID)[1]', 'varchar(40)')) As Id
    From
    	@Inserted.nodes('/row') As I(xml)
    	Full Outer Join @Deleted.nodes('/row') As D(xml)
    	On I.xml.value('(ROWGUID)[1]', 'varchar(40)') = D.xml.value('(ROWGUID)[1]', 'varchar(40)')
    )A
    
    

    Porém o resultado Obtido não é correto, somente o elemento ROWGUID é retornado, quando o necessário seria o Elemento row por completo, percebo que a minha duvida agora é com relação ao uso do método Query.

     

    Alguem poderia me ajudar ao retornar o nó row correspondente ao filtro aplicado ?

     

    Sem mais

     

    Victor Perez

    quarta-feira, 22 de setembro de 2010 12:36
  • Victor,

    Porque você esta utilizando o Full Outer Join?


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    quarta-feira, 22 de setembro de 2010 17:35
  • O conteudo das Variaveis @Deleted e @Inserted, que são do tipo Xml são obtidas em uma trigger, nesse caso os dados podem estar em somente uma das váriáveis (tabelas da trigger), caso estejam nas duas (Update) os dados da coluna chave (rowguid) serão iguais.Normalmnte para evitar dois selects eu faço um Full Outer Join.

    Segue abaixo os meus dados para contato caso seja necessário, porém prefiro que interação seja através do forum para servir como base de conhecimento e resolução de problemas por parte da comunidade.

     

    Messenger: victor.perez@globo.com

    Skype: victorperez2911

    Email: victor.perez@procfit.com.br

     

     

    Sem mais

     

    Victor Perez

    quarta-feira, 22 de setembro de 2010 17:51
  • Victor,

    Você esta utilizando trigger?

    Entendi você esta fazendo uma junção de valores de ambas as tables, mas talvez neste caso você não precisaria utilizar o Full Outer Join, mas sim o Inner Join.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    quarta-feira, 22 de setembro de 2010 18:33
  • Junior Galvão

     

    Primeiramente obrigado pela atenção

     

    Sim, é uma trigger que chama uma procedure passando como parametros as tabelas Inserted e Deleted como Xml, é uma trigger padrão, pois a mesma se encontra em várias tabelas para um processo de replicação de dados, porém, a trigger chama a procedure somente uma vez a cada operação na tabela, mesmo que essa operação afete varias linhas (isso é feito para evitar muitas regras em objetos de dificil gerenciamento como triggers, caso seja necessário alteração na regra, somente a procedure deve ser modificada).

    Com relação inner Join, ele não funcionaria, pois lembre-se, tenho tres situações a contemplar, os dados podem vir somente na @deleted (operação de delete da trigger), somente na @Inserted (operação de insert da trigger) ou em ambas (update da trigger), com o inner, precisaria saber de antemão onde os dados estão para escrever o join, com o full outer join isso não ocorre, mas enfim, acho que esse não é meu problema, pois se executar o select que eu postei com dados em qualquer uma das situações expostas acima funciona normalmente.

     

    O que eu preciso é de uma maneira de utilizar o método query, pois do jeito que eu fiz o resultado esta quase do jeito que necessito.

     

    Sem mais

     

    Victor Perez

    quarta-feira, 22 de setembro de 2010 19:02
  • Victor,

    Entendi, era o que eu havia pensado por você estar utilizando o Full Join.

    Bom, o metodo query esta próximo do que você deseja, mas você deseja retornar o nó row!!!

    Então mas ao invês de declarar o Rowguid, porque você não declara o Row?


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    quarta-feira, 22 de setembro de 2010 19:23
  • Junior

     

    De um exemplo por favor.

     

    Obrigado.

    quarta-feira, 22 de setembro de 2010 19:30
  • Victor,

    Como que eu vou postar uma exemplo, se você possui um ambiente muito particular da sua necessidade.

    Você já consultou o Books On-Line?


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    quarta-feira, 22 de setembro de 2010 19:36
  • declare @dadosxml xml
    
    set @dadosxml = '<?xml version="1.0"?>
    
    <root>
    
    <cliente id="1">
    
    <prod id="321"/>
    
    <prod id="543"/>
    
    <prod id="762"/>
    
    <prod id="325"/>
    
    </cliente>
    
    <cliente id="2">
    
    <prod id="289"/>
    
    <prod id="776"/>
    
    <prod id="335"/>
    
    <prod id="1020"/>
    
    </cliente>
    
    </root>'
    
    --print convert(nvarchar(4000),@dadosxml)
    
    SELECT
    
    t.c.value('../@id[1]','int') as IdCliente,
    
    t.c.value('@id[1]','int') as IdProduto
    
    FROM
    
    @dadosxml.nodes('/root/cliente/prod') as t(c)
    
    dECLARE @x xml 
    SET @x='<Root>
      <row id="1"><name>Larry</name><oflw>some text</oflw></row>
      <row id="2"><name>moe</name></row>
      <row id="3" />
    </Root>'
    SELECT T.c.query('.') AS result
    FROM  @x.nodes('/Root/row') T(c)
    GO
    
    

    Victor,

    Pensei em algo:

     


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    quarta-feira, 22 de setembro de 2010 19:42
  • Junior

     

    Do seu jeito, por algum motivo que eu não sei qual não funciona, pois ele me traz dois nós por Linha, porém, consegui de uma outra forma, relacionar os nós de ambos os Conteudos Xml, porém de uma maneira estranha que eu nem sei como funciona, de uma olhada e veja se tem alguma maneira de melhorar.

     

    Declare @Inserted As Xml = '<row><Coluna1>5</Coluna1><Coluna2>9</Coluna2><ROWGUID>0C8FD950-F360-41DD-8967-27946609A1F6</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>7163F849-40CA-4F3E-80B3-3955767EC8B3</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>963B4DA5-2DC0-43C7-87EB-72F41EA42491</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>1781C061-DB69-493C-AC74-98DDC3AFBEE6</ROWGUID></row><row><Coluna1>5</Coluna1><Coluna2>8</Coluna2><ROWGUID>CE7B07E2-8CC8-4156-8612-DF8659B7AE20</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>72976C1A-4AFF-41F0-BD1F-F7E952CAEDDB</ROWGUID></row>'
    Declare @Deleted As Xml = '<row><Coluna1>4</Coluna1><Coluna2>7</Coluna2><ROWGUID>0C8FD950-F360-41DD-8967-27946609A1F6</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>C04CACF9-CD5C-4F39-9B0F-499DA20808FF</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>7163F849-40CA-4F3E-80B3-3955767EC8B3</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>963B4DA5-2DC0-43C7-87EB-72F41EA42491</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>1781C061-DB69-493C-AC74-98DDC3AFBEE6</ROWGUID></row><row><Coluna1>4</Coluna1><Coluna2>6</Coluna2><ROWGUID>CE7B07E2-8CC8-4156-8612-DF8659B7AE20</ROWGUID></row><row><Coluna1>3</Coluna1><Coluna2>5</Coluna2><ROWGUID>72976C1A-4AFF-41F0-BD1F-F7E952CAEDDB</ROWGUID></row>'
    
    
    Select
    	 @Deleted.query('(/row)[sql:column("Id")]') As Deleted,
    	 @Inserted.query('(/row)[sql:column("Id")]') As Inserted
    From
    (
    Select
    	Row_Number() Over(Order By Isnull(I.xml.value('(ROWGUID)[1]', 'varchar(40)'), D.xml.value('(ROWGUID)[1]', 'varchar(40)'))) As Id
    From
    	@Inserted.nodes('/row') As I(xml)
    	Full Outer Join @Deleted.nodes('/row') As D(xml)
    	On I.xml.value('(ROWGUID)[1]', 'varchar(40)') = D.xml.value('(ROWGUID)[1]', 'varchar(40)')
    )A
    

    Mesmo assim agradeço pela Ajuda.

     

    Sem mais

     

    Victor Perez

     

     

    • Marcado como Resposta VictorPerez quarta-feira, 22 de setembro de 2010 20:28
    quarta-feira, 22 de setembro de 2010 20:28
  • Victor,

    Neste momento, não tenho outra solução, vou tentar entender e analisar a sua.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário]
    sexta-feira, 24 de setembro de 2010 18:07