查询XML列的多行,将子节点提取到多行中

Querying multiple rows of an XML column to extract child nodes into multiple rows

在 SQL 服务器中,我有一个 table 和一个 XML 列,并且从每个 XML,我在父节点下有节点,我想select 节点中的每个值到每个 XML.

的单独行

我该如何完成?

下面是 table 外观的示例:

Name    | Message
John    | <User><Data><Valuelist><Value>123</Value><Value>456</Value><Value>789</Value><Value>654</Value></ValueList></Data></User>
Jack    | <User><Data><ValueList><Value>555</Value><Value>455</Value></ValueList></Data></User>
Jane    | <User><Data><Valuelist><Value>576</Value><Value>854</Value><Value>933</Value></ValueList></Data></User>

为了更清楚起见,下面是我尝试查询的“消息”列中的示例 XML:

<User>
     <Data>
          <ValueList>
              <Value>123</Value>
              <Value>456</Value>
              <Value>789</Value>
              <Value>654</Value>
          </ValueList>
     </Data>
</User>

下面是我希望在结果中看到的内容:

Name    | Values
John    | 123
John    | 456
John    | 789
John    | 654
Jack    | 555
Jack    | 455
Jane    | 576
Jane    | 854
Jane    | 933

我一直在尝试使用以下查询:

select t.Name, x.y.value('(Value)', 'nvarchar(10)') [Values]
from TABLE t
cross apply t.Message.nodes('//ValueList') as x(y)

但它给了我以下错误:

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

我只能 select 使用以下值之一:

select t.Name, x.y.value('(Value[1])', 'nvarchar(10)') [Values]
from TABLE t
cross apply t.Message.nodes('//ValueList') as x(y)

我一直在谷歌上搜索,但找不到我想要做的事情。

我应该在这里做什么?

我的SQL服务器版本是2016 SP2。

提前致谢!

请尝试以下解决方案。

SQL

-- DDL and sample data population, start
DECLARE @tbl table (ID INT IDENTITY PRIMARY KEY, Name VARCHAR(20), Message XML);
INSERT INTO @tbl (Name, Message) VALUES
('John', N'<User><Data><ValueList><Value>123</Value><Value>456</Value><Value>789</Value><Value>654</Value></ValueList></Data></User>'),
('Jack', N'<User><Data><ValueList><Value>555</Value><Value>455</Value></ValueList></Data></User>'),
('Jane', N'<User><Data><ValueList><Value>576</Value><Value>854</Value><Value>933</Value></ValueList></Data></User>');
-- DDL and sample data population, end

SELECT t.ID, t.Name
    , c.value('(./text())[1]', 'nvarchar(10)') AS [Values]
FROM @tbl AS t
CROSS APPLY Message.nodes('/User/Data/ValueList/Value') as t1(c);

输出

+----+------+--------+
| ID | Name | Values |
+----+------+--------+
|  1 | John |    123 |
|  1 | John |    456 |
|  1 | John |    789 |
|  1 | John |    654 |
|  2 | Jack |    555 |
|  2 | Jack |    455 |
|  3 | Jane |    576 |
|  3 | Jane |    854 |
|  3 | Jane |    933 |
+----+------+--------+