在SQL Server中查询XML数据

时间:2017-08-18 04:50:48

标签: sql sql-server xml sql-server-2008 sql-server-2012

在我的一个表列(nvarchar)中,数据以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>

我查了几个SQL Server函数,我需要定义命名空间才能提取出来的值。

正确格式化,以便我可以知道要检索的字段。

<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>

预期输出为

Disp_Dest, LowPressureRinse
Disp_Dest, ShortInlet

您认为使用SQL Server XML相关功能可以实现这一目标吗?

感谢。

2 个答案:

答案 0 :(得分:1)

以下是使用ValueQuery方法

执行此操作的一种方法
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) 

答案 1 :(得分:0)

您不应将XML存储为字符串。如果你可以改变它,你应该真正使用本机类型的XML列!

原因:XML不是存储为您看到的字符串,而是存储为层次结构树。处理此树不需要字符串解析。但在您的情况下,您将不得不在每次调用中重新创建此层次结构树。这非常贵!

试试这样:

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);

只需将@mockup更改为您实际的表名称并调整列名称。

第一个APPLY将输入XML,第二个APPLY使用.nodes()获取内部<Datatypevalue>元素。

结果

+----+-------+-----------+-----------------------------+------------+--------+------------------+
| 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              |
+----+-------+-----------+-----------------------------+------------+--------+------------------+