使用 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.price
和books.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,那么肯定会! - 不包含以<?xml version="1.0" encoding="UTF-8"?>
开头的 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的主要内容,如果未能解决你的问题,请参考以下文章