更新在数据库中存储为字符串的 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 列的 &lt;Salary&gt;DifferingSalary&lt;/Salary&gt; 更新为 &lt;Salary&gt;10000&lt;/Salary&gt;

试过了:

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】:

您可以尝试以下方法。

它展示了如何在以下情况下修改&lt;salary&gt;元素值:

xmldata 列是 XML 数据类型。 xmldata 列是 NVARCHAR(MAX) 数据类型。

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 节点的主要内容,如果未能解决你的问题,请参考以下文章

读取在java中存储为字符串的xml [重复]

处理 XML 更改的好方法

Nhibernate - xml 列格式不正确

如何创建更新查询以将存储为文本的 xml 值提取到新列中

如何在QT中将xml节点数据转换为字符串[重复]

如何在 XSLT 中拆分数据并存储在多个节点中