使用 T-SQL 中另一个(非 xml)列的值更新 XML
Update XML with value from another (non-xml) column in T-SQL
我有一个 table,其中有两个 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 数据来自哪里。假设书籍列中已经存在 XML 数据。
我知道如何用静态值更新 table
UPDATE books
SET book.modify('insert <Price>10.99</Price><Discount>20.00</Discount> after (/book/Store/Address)[1]')
此处不考虑性能。
不可能在一个语句中进行两次修改。
在这种情况下,您可以通过首先组合两个值然后一次插入它们来解决这个问题。
我使用 可更新的 CTE 来实现:
CREATE TABLE books (
ID INT NOT NULL,
price NUMERIC(4,2),
discount NUMERIC(2,2),
book XML
);
--用数据
填充table
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;
我有一个 table,其中有两个 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 数据来自哪里。假设书籍列中已经存在 XML 数据。
我知道如何用静态值更新 table
UPDATE books
SET book.modify('insert <Price>10.99</Price><Discount>20.00</Discount> after (/book/Store/Address)[1]')
此处不考虑性能。
不可能在一个语句中进行两次修改。
在这种情况下,您可以通过首先组合两个值然后一次插入它们来解决这个问题。
我使用 可更新的 CTE 来实现:
CREATE TABLE books (
ID INT NOT NULL,
price NUMERIC(4,2),
discount NUMERIC(2,2),
book XML
);
--用数据
填充tableINSERT 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;