更新在数据库中存储为字符串的 XML 节点
Posted
技术标签:
【中文标题】更新在数据库中存储为字符串的 XML 节点【英文标题】:Update an XML node that is stored as string in Database 【发布时间】:2020-07-21 13:26:38 【问题描述】:我可以了解将 XML 节点的值(每行不同)替换为新值(所有行通用)的 SQL 查询吗?
如果 XML 是:
<?xml version="1.0" encoding="utf-16"?>
<EmployeeDetail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>MyName</Name>
<Age>20</Age>
<Salary>15000</Salary>
</EmployeeDetail>
我需要将所有 XML 列的 <Salary>DifferingSalary</Salary>
更新为 <Salary>10000</Salary>
试过了:
DECLARE @salary VARCHAR(10) = '10000';
UPDATE TABLE_NAME
SET [COLUMN_NAME].modify('replace value of
(/EmployeeDetail/Salary/text())[1]
with (sql:variable("@salary"))
');
输出:
无法调用 nvarchar(max) 上的方法。
注意:XML 以字符串形式存储在数据库中。
提前致谢!
【问题讨论】:
在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:***.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试实现它。 (3) 基于上述#1 中的样本数据的期望输出。 (4) 你的 SQL Server 版本 (SELECT @@version;) 我已经添加了。请检查更新。 【参考方案1】:您可以尝试以下方法。
它展示了如何在以下情况下修改<salary>
元素值:
SQL #1
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl ( xmldata) VALUES
(N'<?xml version="1.0" encoding="utf-16"?>
<EmployeeDetail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>MyName</Name>
<Age>20</Age>
<Salary>15000</Salary>
</EmployeeDetail>');
-- DDL and sample data population, end
-- before
SELECT * FROM @tbl;
DECLARE @salary VARCHAR(10) = '10000';
UPDATE @tbl
SET xmldata.modify('replace value of
(/EmployeeDetail/Salary/text())[1]
with (sql:variable("@salary"))
');
-- after
SELECT * FROM @tbl;
SQL #2
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata NVARCHAR(MAX));
INSERT INTO @tbl ( xmldata) VALUES
(N'<?xml version="1.0" encoding="utf-16"?>
<EmployeeDetail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>MyName</Name>
<Age>20</Age>
<Salary>15000</Salary>
</EmployeeDetail>');
DECLARE @realXML TABLE (ID INT, realXML XML);
-- DDL and sample data population, end
-- populate temporary table
INSERT INTO @realXML
SELECT ID, cast(xmldata AS XML)
FROM @tbl;
DECLARE @salary VARCHAR(10) = '10000';
/*
Unfortunately, we can not assign from a xml.modify() statement.
Modify works on a variable and a column only.
Also, we cannot use modify on a CAST().
*/
-- update temporary table
UPDATE @realXML
SET realXML.modify('replace value of
(/EmployeeDetail/Salary/text())[1]
with (sql:variable("@salary"))
');
-- update real table
UPDATE tbl
SET xmldata = CAST(t.realXML AS NVARCHAR(MAX))
FROM @realXML AS t INNER JOIN @tbl AS tbl
ON tbl.ID = t.ID;
【讨论】:
无法调用 nvarchar(max) 上的方法。是我得到的错误。 我更新了答案。使用适当的数据类型总是更好,在这种情况下是 XML 数据类型。以上是关于更新在数据库中存储为字符串的 XML 节点的主要内容,如果未能解决你的问题,请参考以下文章