web-dev-qa-db-ja.com

XQueryはXMLデータを更新しません

スクリプトを実行してXML列を更新しようとしています。

UPDATE DataImpTable
SET serviceData.modify('replace value of (/SMObjInfo/CentralData/SMData/CentralSDItem/ControlData/text())[1] with "9876"')
WHERE identifier=5
<SMObjInfo xmlns="DataService/1.0.0.0" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <CentralData>
    <SMData>
      <CentralSDItem>
        <ControlData>1234</ControlData>
      </CentralSDItem>
    </SMData>
  </CentralData>
</SMObjInfo>

ControlDataの値を9876に変更しますが、/SMObjInfo/CentralData/SMData/CentralSDItem/ControlData値のXMLで値が変更されていないようです。

型付きXMLと型なしXMLは関係ありますか?

7
S S

modify関数で名前空間を宣言する必要があります。

このようなもの:

DECLARE @xml xml = N'<SMObjInfo xmlns="DataService/1.0.0.0" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <CentralData>
    <SMData>
      <CentralSDItem>
        <ControlData>1234</ControlData>
      </CentralSDItem>
    </SMData>
  </CentralData>
</SMObjInfo>';
SET @xml.modify('
    declare default element namespace "DataService/1.0.0.0";
    replace value of (/SMObjInfo/CentralData/SMData/CentralSDItem/ControlData/text())[1]
    with "6789"
    ');
PRINT CONVERT(nvarchar(max), @xml);

元のxmlフラグメントで、使用されない次の名前空間を宣言しています。

xmlns:i="http://www.w3.org/2001/XMLSchema-instance"

実際のxmlドキュメントがこの名前空間を使用していて、それらの要素を変更する場合は、次の宣言を@xml.modify関数に追加する必要があります。

declare namespace i="http://www.w3.org/2001/XMLSchema-instance";

結果(読みやすいようにフォーマットされています):

<SMObjInfo xmlns="DataService/1.0.0.0" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <CentralData>
        <SMData>
            <CentralSDItem>
                <ControlData>6789</ControlData>
            </CentralSDItem>
        </SMData>
    </CentralData>
</SMObjInfo>

SQLServerScience.com で、modify関数に関するブログ記事をいくつかの例とともに書きました。

11
Max Vernon

テーブルにXMLがある場合は、SETの代わりにUPDATEを使用する必要があり、 WITH XMLNAMESPACES を使用してXML_DML式の外に名前空間宣言を置くことができます。

with xmlnamespaces(default 'DataService/1.0.0.0')
update DataImpTable
set serviceData.modify('replace value of (/SMObjInfo/CentralData/SMData/CentralSDItem
                                            /ControlData/text())[1] with "9876"')
where identifier=5
9
Mikael Eriksson