我得到了一些我需要“粉碎”的XML数据(我认为这是正确的术语)。那就是我需要把它放到SQL表中。这是一个例子,一个有效的查询,但我被告知这是低效的。如果您知道更有效的方法,请告诉我。
以下是一些示例XML,2个不起作用的查询,以及一个:
DECLARE @XmlReportParameters NVARCHAR (MAX) = N'<?xml version="1.0" encoding="utf-16"?>
<Customers>
<Customer>
<Name>Sri Patel</Name>
<FavColors>
<FavColor>Red</FavColor>
<FavColor>Blue</FavColor>
<FavColor>Green</FavColor>
</FavColors>
</Customer>
<Customer>
<Name>Jane Doe</Name>
<FavColors>
<FavColor>Violet</FavColor>
<FavColor>Mauve</FavColor>
</FavColors>
</Customer>
</Customers>
'
DECLARE @doc XML;
DECLARE @XmlTable TABLE
(
XmlColumn XML NULL
);
SET @doc = @XmlReportParameters;
INSERT INTO @XmlTable
( XmlColumn )
VALUES
( @doc )
-- Wrong Way
SELECT
tbl.col.value('(Name)[1]', 'nvarchar(max)') AS CustomerName
,tbl.col.value('(FavColors/FavColor)[1]', 'nvarchar(max)') AS FavColor
FROM
@XmlTable xt
CROSS APPLY XmlColumn.nodes('/Customers/Customer') tbl(col);
-- Still wrong (but I'm not sure why)
SELECT
tbl.col.value('(../Name)[1]', 'nvarchar(max)') AS CustomerName
,tbl.col.value('(FavColor)[1]', 'nvarchar(max)') AS FavColor
FROM
@XmlTable xt
CROSS APPLY XmlColumn.nodes('/Customers/Customer/FavColors') tbl(col);
-- Right Way
SELECT
tbl.col.value('(../../Name)[1]', 'nvarchar(max)') AS CustomerName
,tbl.col.value('(.)[1]', 'nvarchar(max)') AS FavColor
FROM
@XmlTable xt
CROSS APPLY XmlColumn.nodes('/Customers/Customer/FavColors/FavColor') tbl(col);
返回:
CustomerName FavColor
------------ ----------
Sri Patel Red
Jane Doe Violet
CustomerName FavColor
------------ ----------
Sri Patel Red
Jane Doe Violet
CustomerName FavColor
------------ ----------
Sri Patel Red
Sri Patel Blue
Sri Patel Green
Jane Doe Violet
Jane Doe Mauve
答案 0 :(得分:3)
这里的“ineffecency”是使用Parent Axis遍历备份文档以获取名称。执行此操作的首选方法是使用多个APPLY运算符。第一个将突出显示Customer节点,然后是第二个用于投影FavColors节点的节点。像这样:
SELECT
CustomerNode.e.value('(Name)[1]', 'nvarchar(max)') AS CustomerName
,FavColorNode.e.value('(.)[1]', 'nvarchar(max)') AS FavColor
FROM
@XmlTable xt
CROSS APPLY XmlColumn.nodes('/Customers/Customer') CustomerNode(e)
CROSS APPLY CustomerNode.e.nodes('FavColors/FavColor') FavColorNode(e);
虽然它们之间的差异可能不适用于大多数情况。
答案 1 :(得分:1)
正如我之前在另一个问题上告诉过你的那样,解决方案是对.nodes()
的分层调用
SELECT
cust.value('(Name/text())[1]', 'nvarchar(max)') AS CustomerName
,col.value('text()[1]', 'nvarchar(max)') AS FavColor
FROM
@XmlTable xt
CROSS APPLY XmlColumn.nodes('/Customers/Customer') A(cust)
CROSS APPLY cust.nodes('FavColors/FavColor') AS B(col) ;
这将首先返回所有<Customer>
和 - 下面的 - 相关的<FavColor>
:
Customer FavColor
Sri Patel Red
Sri Patel Blue
Sri Patel Green
Jane Doe Violet
Jane Doe Mauve