sql-server - 在 SQL Server 2014 中将 XML 数据转换为关系格式时遇到问题

标签 sql-server xml xpath xquery sql-server-2014

我收到了一些需要“分解”的 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

最佳答案

这里的“低效率”是使用父轴来遍历备份文档以获取名称。执行此操作的首选方法是使用多个 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);

尽管对于大多数情况来说,它们之间的差异可能并不重要。

关于sql-server - 在 SQL Server 2014 中将 XML 数据转换为关系格式时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48950651/

相关文章:

sql-server - 微软 SQL : How are variables and aliases evaluated within query execution?

sql-server - col1 的计数超过 col2 的 order

SQL存储过程执行时间之谜

xml - 使用 xsl 从 xml 中删除 xmlns 命名空间

android - BottomAppBar无法正确加载

javascript - 如何使用 css 或 xpath 选择器拒绝指定 HTML 标签

sql - 在 SQL Server 中加密列上的运算符搜索

php - 缓存来自远程 URL 的 XML 提要

ruby-on-rails - nokogiri 从 xml 到数组的多个元素

python - 难以缩小复选框的 XPath 范围