0

我正在处理 sql server 中的一个表,它将 xml 文件存储在一个列中。在那个 xml 文件中,我正在做一些更改。XML 文件如下所示:

<Report version=1>
 <Title>
   <Student>
         <InputNumber type="int" min="0" max="100" name="age" description="Age 
          of student">
            <Value>20</Value>
         </InputNumber>
         <InputNumber type="int" min="0" max="100" name="height" 
         description="height of student">
             <Value>170</Value>
         </InputNumber>
   </Student>
 </Title>
</Report>

我理解修改功能用于更新标签之间存在的属性或文本的用法:

UPDATE student
SET dataxml.modify('replace value of (/Report/@version)[1] with "2"')
WHERE id=10
or
UPDATE student
SET dataxml.modify('replace value of (/Report/Title/Student/InputNumber[1]/Value[1]/text())[1] with "21"')
WHERE id=10

但现在我想用另一个标签替换整个标签,即

         <InputNumber type="int" min="0" max="100" name="height" 
         description="height of student">
             <Value>170</Value>
         </InputNumber>

         <InputText name="height" 
         description="height of student">
             <Value>170 cm</Value>
         </InputText>

我在互联网上找到了类似的东西并尝试了。

Update Student
   set dataxml = replace(cast(dataxml as nvarchar(max)),'/Report/Title/Student/InputNumber[2]>','InputText>')
WHERE id=10

它说更新成功。但我没有看到 XML 的变化。我怎样才能做到这一点?

4

1 回答 1

1

首先:您的 XML 无效。属性version=1必须是version="1"。第二:动词标签只是一个类似<Student>or的标记</Student>,但是具有属性和嵌套子节点的整个节点称为节点或 - 作为一种特殊类型的节点 -元素

现在到你的问题:

我们需要一个声明的表来模拟您的问题:

DECLARE @student TABLE(ID INT IDENTITY, dataxml XML);
INSERT INTO @student VALUES
(N'<Report version="1">
 <Title>
   <Student>
         <InputNumber type="int" min="0" max="100" name="age" description="Age of student">
            <Value>20</Value>
         </InputNumber>
         <InputNumber type="int" min="0" max="100" name="height" description="height of student">
             <Value>170</Value>
         </InputNumber>
   </Student>
 </Title>
</Report>');

--这是我们要插入的新元素(更好:想用来替换另一个)

DECLARE @newElement XML=
N'<InputText name="height" description="height of student">
    <Value>170 cm</Value>
  </InputText>';

--approach one calls `.modify()` twice:

UPDATE @student SET dataxml.modify('insert sql:variable("@newElement") after (/Report/Title/Student/InputNumber[@name="height"])[1]');
UPDATE @student SET dataxml.modify('delete (/Report/Title/Student/InputNumber[@name="height"])[1]');

SELECT * FROM @student; 

--方法二使用FLWOR-XQuery

UPDATE @student SET dataxml=dataxml.query('<Report version="{/Report/@version}">
                                           {<Title> 
                                            <Student>
                                            {
                                            for $elmt in /Report/Title/Student/*
                                            return
                                            if(local-name($elmt)="InputNumber" and $elmt[@name="height"]) then
                                               <InputText name="height" description="height of student">
                                                   <Value>{$elmt/Value/text()} cm</Value>
                                               </InputText>
                                            else
                                                $elmt
                                            }
                                            </Student>
                                           </Title>}
                                           </Report>');

简而言之,这两个想法:

1)我们在应该替换的元素之后插入新元素,并在单独的步骤中将其删除。

2) 我们通过运行内部节点列表通过 XQuery 重新创建 XML,<Student>并插入新内容而不是现有节点。

于 2020-04-16T18:32:45.853 回答