Daksh Dutta
Daksh Dutta

Reputation: 193

How to fetch data from XML with different nodes as column in SQL Server

I have a XML from which I am trying to select rows by the table name from the XML but the columns count is different on each node.

Below is my XML:

<tables>
    <table>
      <name>Table1</name>
       <attr>
         <id>1</id>
         <col1>123</col1>
          <col2>345</col2>
       </attr>
        <attr>
         <id>2</id>
         <col3>123</col3>
       </attr>
        <attr>
         <id>4</id>
          <col2>123</col2>
       </attr>
    </table>
</tables> 

Now I am querying by below query:

SELECT T.N.VALUE('id','nvarchar(100)') as id,
       T.N.VALUE('col1','nvarchar(100)') as col1,
       T.N.VALUE('col2','nvarchar(100)') as col2,
       T.N.VALUE('col3','nvarchar(100)') as col3 
FROM @input.nodes('/tables/table/attr') AS T(N) 
CROSS APPLY @input.nodes('/tables/table/name') AS S(N) 
WHERE S.N.value('name','varchar(100)')='Table1'

But I get an error

XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

But I am expecting to get:

id | col1 | col2 | col3
---+------+------+------
 1 | 123  | 345  | NULL
 2 | NULL | NULL | 123
 4 | NULL | 123  | NULL

Upvotes: 0

Views: 249

Answers (1)

David Browne - Microsoft
David Browne - Microsoft

Reputation: 88996

Like this:

declare @input xml = '<tables>
    <table>
      <name>Table1</name>
       <attr>
         <id>1</id>
         <col1>123</col1>
          <col2>345</col2>
       </attr>
        <attr>
         <id>2</id>
         <col3>123</col3>
       </attr>
        <attr>
         <id>4</id>
          <col2>123</col2>
       </attr>
    </table>
</tables> 
'


SELECT a.N.value('(id)[1]','nvarchar(100)') as id,
       a.N.value('(col1)[1]','nvarchar(100)') as col1,
       a.N.value('(col2)[1]','nvarchar(100)') as col2,
       a.N.value('(col3)[1]','nvarchar(100)') as col3 
FROM @input.nodes('/tables/table') AS t(N) 
CROSS APPLY T.N.nodes('attr') AS a(N) 
WHERE t.N.value('(name)[1]','varchar(100)')='Table1'

Upvotes: 3

Related Questions