使用 T-SQL 中另一个(非 xml)列的值更新 XML

Posted

技术标签:

【中文标题】使用 T-SQL 中另一个(非 xml)列的值更新 XML【英文标题】:Update XML with value from another (non-xml) column in T-SQL 【发布时间】:2017-02-12 01:49:42 【问题描述】:

我有一个表,其中包含两个 NUMERIC 类型的字段和一个 XML 类型的字段。这是一个粗略的示例:

CREATE TABLE books (
        ID INT NOT NULL,
        price NUMERIC(4,2),
        discount NUMERIC(2,2),
        book XML
);

XML 值看起来像,比如说,

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <title>Harry Potter</title>
    <author>J K Rowling</author>
    <Store>
        <Name>Burke and Burkins</Name>
        <Address>Some St, Somewhere, Some City</Address>
    </Store>
</book>

现在我的问题是,使用xml.modify(),如何在Store 下添加两个xpath,价格和折扣分别来自books.pricebooks.discount

<?xml version="1.0" encoding="UTF-8"?>
<book>
    <title>Harry Potter</title>
    <author>J K Rowling</author>
    <Store>
        <Name>Burke and Burkins</Name>
        <Address>Some St, Somewhere, Some City</Address>
        <Price>value from books.price from the same row</Price>
        <Discount>value from books.discount from the same row</Discount>
    </Store>
</book>

这是一个粗略的例子,所以请不要担心 XML 数据的来源。假设 book 列已经存在 XML 数据。

我知道如何用静态值更新表格,

UPDATE books
SET book.modify('insert <Price>10.99</Price><Discount>20.00</Discount> after (/book/Store/Address)[1]')

这里不考虑性能。

【问题讨论】:

【参考方案1】:

不可能在一个语句中进行两次修改。

在这种情况下,您可能会先将这两个值组合起来,然后一次插入,从而解决这个问题。

我使用可更新的 CTE 来实现:

CREATE TABLE books (
        ID INT NOT NULL,
        price NUMERIC(4,2),
        discount NUMERIC(2,2),
        book XML
);

--用数据填表

INSERT INTO books VALUES(1,10.5,.5,
'<book>
    <title>Harry Potter</title>
    <author>J K Rowling</author>
    <Store>
        <Name>Burke and Burkins</Name>
        <Address>Some St, Somewhere, Some City</Address>
    </Store>
</book>');

--这是实际的查询

WITH CTE AS
(
    SELECT *
          ,(SELECT price AS Price,discount AS Discount FOR XML PATH(''),TYPE) AS XmlNode 
    FROM books
)
UPDATE CTE SET book.modify('insert sql:column("XmlNode") after (/book/Store/Address)[1]');

--检查结果

SELECT *
FROM books;

--清理(认真对待真实约会!

GO
--DROP TABLE books;

一个提示

您的 XML 列,如果它真的是 XML,那么肯定会! - 不包含以&lt;?xml version="1.0" encoding="UTF-8"?&gt; 开头的 XML。内部编码始终是 unicode(ucs-2,几乎是 utf-16)并且无法更改。如果你传入一个声明,它要么被省略,要么你会得到一个错误。

更新

另一种方法是先读取 XML 的值,然后重新构建它:

WITH CTE AS
(
    SELECT *
          ,(SELECT b.value('title[1]','nvarchar(max)') AS [title]
                  ,b.value('author[1]','nvarchar(max)') AS [author]
                  ,b.value('(Store/Name)[1]','nvarchar(max)') AS [Store/Name]
                  ,b.value('(Store/Address)[1]','nvarchar(max)') AS [Store/Address]
                  ,price AS [Store/Price]
                  ,discount AS [Store/Discount]
            FROM book.nodes('book') AS A(b)
            FOR XML PATH('book'),TYPE
            ) AS bookNew
    FROM books
)
UPDATE CTE SET book=bookNew;

【讨论】:

你说得对,我的 XML 中没有 。我从自动添加该行的编辑器中复制了它。我会尝试你的解决方案,让你知道它是如何进行的。实际上,它是一个更大的 XML,需要添加大约 20 个字段:)。我会为您对问题的深入研究给予支持。谢谢。 第一个解决方案适用于我的情况,因为我想要插入的所有节点都在同一个父节点(存储)下。必须有另一个使用 sql:variable 的解决方案,但我找不到任何可以让我插入多个值的解决方案。所以将此标记为答案。谢谢。

以上是关于使用 T-SQL 中另一个(非 xml)列的值更新 XML的主要内容,如果未能解决你的问题,请参考以下文章

如何根据火花DataFrame中另一列的值更改列的值

使用同一表中另一列的键更新 mysql 列

如何在 ag-Grid Angular 设置中访问 c​​olumnDefs 中另一列的值?

获取 ant.design 表列中另一列的值?

使用同一表中另一列的数据计数更新一列? [关闭]

根据火花数据框中另一列的值查找列的最大值?