sql查询更新存储在列中的xml节点

时间:2015-04-15 03:25:49

标签: sql-server xml sql-update xml-column

我正在开发一个项目,我正在使用一个表,其中xml数据存储在其中一列中。我正在尝试根据xml_id和xml节点的位置更新整个xml节点,但我无法做到这一点我尝试了以下查询,但它只更新了xml节点的值而不是节点的整个键/值。

表格结构

enter image description here

查询以更新xml节点的值

update tblCCBT_Step_Page_Text_Xml
set Xml_XmlData.modify('replace value of (/page/*[position()=1]/text())[1] 
                with "test value"')where xml_id = 101

所以现在我尝试了以下查询来更新整个内部节点

update tblCCBT_Step_Page_Text_Xml
set Xml_XmlData.modify('replace value of (/page/*[position()=1]/text())[1] 
                with "<testnode>test value</testnode>"') where xml_id = 101

但是我在尝试这样做时遇到错误

  

Msg 9306,Level 16,State 1,Line 2
  XQuery [tblCCBT_Step_Page_Text_Xml.Xml_XmlData.modify()]:&#39;替换&#39;的目标不能是联合类型,找到&#39;(元素(*,xdt:无类型)|注释|处理 - 指令|文本)?&#39;。

这是我的xml存储在

列中
<page name="page0" identifier="ff-102-101-101">
     <backBut>test value</backBut>
     <printBut>Print</printBut>
     <quiz1>Click on the circle that best describes your</quiz1>
     <quiz2>Continue</quiz2>
     <quiz3>Finish</quiz3>
     <quiz4>You are now on questions </quiz4>
     <quiz5>out of</quiz5>
     <quiz6>Please answer each question before continuing.</quiz6>
 </page>

现在在xml以上我试图替换 -

<backBut>test value</backBut> with <testnode>test value</testnode>

请建议如何实现这一目标。感谢

2 个答案:

答案 0 :(得分:4)

您可以使用插入/删除方法。

您的代码在SQL2008R2上没有给我带来任何错误。 但它也没有给出理想的结果。

该语句导致替换节点的文本值,而不是替换节点本身,如下所示。

<page name="page0" identifier="ff-102-101-101">
  <backBut>&lt;testnode&gt;test value&lt;/testnode&gt;</backBut>
  <printBut>Print</printBut>
  <quiz1>Click on the circle that best describes your</quiz1>
  <quiz2>Continue</quiz2>
  <quiz3>Finish</quiz3>
  <quiz4>You are now on questions </quiz4>
  <quiz5>out of</quiz5>
  <quiz6>Please answer each question before continuing.</quiz6>
</page>

你可以通过插入/删除来实现它:

首先插入新节点:

UPDATE tblCCBT_Step_Page_Text_Xml
SET Xml_XmlData.modify('insert <testnode>test value</testnode> into /page[1]')
WHERE xml_id = 101

然后只需删除旧节点:

UPDATE tblCCBT_Step_Page_Text_Xml
SET Xml_XmlData.modify('delete (/page/backBut)[1]')
WHERE xml_id =101

答案 1 :(得分:1)

不敢相信我做到了:)

declare @t table (
    Id int,
    XMLData xml
);

insert into @t (Id, XMLData)
values
    (101, N'<page name="page0" identifier="ff-102-101-101">
     <backBut>test value</backBut>
     <printBut>Print</printBut>
     <quiz1>Click on the circle that best describes your</quiz1>
     <quiz2>Continue</quiz2>
     <quiz3>Finish</quiz3>
     <quiz4>You are now on questions </quiz4>
     <quiz5>out of</quiz5>
     <quiz6>Please answer each question before continuing.</quiz6>
 </page>');

-- Before modification
select * from @t;

update t set XMLData = nt.ModXML
from @t t
    inner join (
        select t2.Id, t2.XMLData.query('
element page {
    /page/@*,
    for $n in /page/*
    return
        if (local-name($n) = "backBut") then
            <testnode>test value</testnode>
        else
            $n
}') as [ModXML]
        from @t t2
    ) nt on t.Id = nt.Id
where t.Id = 101;

-- After modification
select * from @t;

正如您所看到的,严格来说,它不是XML更新 - 我正在替换整个XML字段的内容。此外,如果结构更复杂,它可能会停止工作。而且,性能也是一个问题。