简体   繁体   中英

Querying XML Data in SQL Server

In one of my table column (nvarchar), the data was stored in XML format.

In this example, the data looks like this :

<Datatype id="76" name="Disp_Dest" hdl="47/4/SB8_3-910-8243-19/0/76" odobjid="385">
    <Datatypevalue id="1" name="LowPressureRinse" />
    <Datatypevalue id="0" name="ShortInlet" />
</Datatype>

I checked a few SQL Server function, I need to define namespace in order to extract values out.

Formatted this properly so I can know which field to retrieve.

<Datatype id="76" name="Disp_Dest" hdl="47/4/SB8_3-910-8243-19/0/76" odobjid="385">
    <Datatypevalue id="1" name="LowPressureRinse" />
    <Datatypevalue id="0" name="ShortInlet" />
</Datatype>

The expected output would be

Disp_Dest, LowPressureRinse
Disp_Dest, ShortInlet

Do you think this is achievable using SQL Server XML related functions ?

Thanks.

Here is one way to do it using Value and Query method

DECLARE @xml XML = '<Datatype id="76" name="Disp_Dest" hdl="47/4/SB8_3-910-8243-19/0/76" odobjid="385">
        <Datatypevalue id="1" name="LowPressureRinse" />
        <Datatypevalue id="0" name="ShortInlet" />
</Datatype>'

SELECT CONVERT(VARCHAR(1000), @xml.query('data(Datatype/@name[1])')),
       c.value('@name', 'varchar(1000)')
FROM   @xml.nodes('Datatype/Datatypevalue') x (c) 

You should not store XML as a string. If you can change this, you should really use a natively typed XML column!

Why: The XML is not stored as the string you see, but as a hierarchy tree. Dealing with this tree does not need string parsing. But in your case you'll have to re-create this hierarchy tree in each call. This is very expensive!

Try it like this:

DECLARE @mockup TABLE(ID INT IDENTITY,YourStringXML XML);
INSERT INTO @mockup VALUES
(N'<Datatype id="76" name="Disp_Dest" hdl="47/4/SB8_3-910-8243-19/0/76" odobjid="385">
    <Datatypevalue id="1" name="LowPressureRinse" />
    <Datatypevalue id="0" name="ShortInlet" />
</Datatype>')
,(N'<Datatype id="11" name="SomeOther" hdl="blah" odobjid="111">
    <Datatypevalue id="1" name="blubb" />
    <Datatypevalue id="0" name="foo" />
</Datatype>');

SELECT m.ID
      ,A.Casted.value(N'/Datatype[1]/@id',N'int') AS dt_Id
      ,A.Casted.value(N'/Datatype[1]/@name',N'nvarchar(max)') AS dt_name
      ,A.Casted.value(N'/Datatype[1]/@hdl',N'nvarchar(max)') AS dt_hdl
      ,A.Casted.value(N'/Datatype[1]/@odobjid',N'nvarchar(max)') AS dt_odobjid
      ,dtv.value(N'@id',N'int') AS dtv_Id
      ,dtv.value(N'@name',N'nvarchar(max)') AS dtv_name
FROM @mockup AS m
OUTER APPLY (SELECT CAST(m.YourStringXML AS XML)) AS A(Casted)
OUTER APPLY A.Casted.nodes(N'/Datatype/Datatypevalue') AS B(dtv);

Just change @mockup to your actual table's name and adjust the column names.

The first APPLY will get the XML typed, the second APPLY uses .nodes() to get the internal <Datatypevalue> elements.

The result

+----+-------+-----------+-----------------------------+------------+--------+------------------+
| ID | dt_Id | dt_name   | dt_hdl                      | dt_odobjid | dtv_Id | dtv_name         |
+----+-------+-----------+-----------------------------+------------+--------+------------------+
| 1  | 76    | Disp_Dest | 47/4/SB8_3-910-8243-19/0/76 | 385        | 1      | LowPressureRinse |
+----+-------+-----------+-----------------------------+------------+--------+------------------+
| 1  | 76    | Disp_Dest | 47/4/SB8_3-910-8243-19/0/76 | 385        | 0      | ShortInlet       |
+----+-------+-----------+-----------------------------+------------+--------+------------------+
| 2  | 11    | SomeOther | blah                        | 111        | 1      | blubb            |
+----+-------+-----------+-----------------------------+------------+--------+------------------+
| 2  | 11    | SomeOther | blah                        | 111        | 0      | foo              |
+----+-------+-----------+-----------------------------+------------+--------+------------------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM