Search code examples
sqlsql-serverxmlt-sqlchild-nodes

Select values from XML in SQL


I need to select values from an XML document. These values are stored as childnodes as follows:

   <customers>
        <customer>
            <kunnr>1</kunnr>
            <kdgrp>2</kdgrp>
        </customer>
        <customer>
            <kunnr>2</kunnr>
            <kdgrp>2</kdgrp>
        </customer>
    </customers>

I need to select the values of kunnr and kdgrp for every customer node. I expect a result like this:

kunnr       kdgrp
1           2
2           2

What I tried so far:

SELECT  @xml.query('/customers/customer/kunnr') AS KUNNR,
        @xml.query('/customers/customer/kdgrp') AS KDGRP

This results in one row with two colums containing XML:

KUNNR                                     KDGRP
<kunnr>1</kunnr><kunnr>2</kunnr>          <kdgrp>2</kdgrp><kdgrp>2</kdgrp>

Another try:

SELECT  C.value('/kunnr/text()','nvarchar(10)') as KUNNR,
        C.value('/kdgrp/text()','nvarchar(10)') as KDGRP
from @xml.nodes('/customers/customer') AS T(C);

This resulted in the following error message:

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

Solution

  • Maybe something like this:

    DECLARE @xml XML
    SET @xml='<customers>
            <customer>
                <kunnr>1</kunnr>
                <kdgrp>2</kdgrp>
            </customer>
            <customer>
                <kunnr>2</kunnr>
                <kdgrp>2</kdgrp>
            </customer>
        </customers>'
    

    And then a query like this:

    SELECT
        c.value('kunnr[1]', 'nvarchar(10)') AS kunnr,
        c.value('kdgrp[1]', 'nvarchar(10)') AS kdgrp
    FROM
        @xml.nodes('//customers/customer') as t(c)
    

    This will give you this result:

    kunnr  kdgrp
    1      2
    2      2