none
XMLデータ型列:値がNullの要素の編集 RRS feed

  • 質問

  • どなたかご教示いただけないでしょうか。

    XMLデータ型で値がNullの要素に対する編集の手段についてです。

    いくつかの要素の値はNullになっているのですが、その要素の値に対してmodifyメソッドのreplace value of ~を使って値を入れようとしても更新できませんでした。原因は XMLデータ型列の空白の要素 でご回答いただいた「SQL Server DB での NULL を xml 上で表すには、既定では、要素が存在しない状態」のためと考えています。

    【データ】

    テーブル名:[Data]
    XMLデータ:列名[XML]

    <root  xml:space="preserve">
        <elm n="3">100</elm>
        <elm n="2" />
        <elm n="1" />
    </root>

    【使ったSQL文】
    UPDATE [dbo].[Data] SET [XML].modify('replace value of (/root/elm[@n="2"]/text())[1] with 200')
    ※SQL文を修正しました。/text()を追記

    【期待した更新結果】
    <root  xml:space="preserve">
        <elm n="3">100</elm>
        <elm n="2">200</elm>
        <elm n="1" />
    </root>

    【実際の更新結果】
    <root  xml:space="preserve">
        <elm n="3">100</elm>
        <elm n="2" />
        <elm n="1" />
    </root>

    対応案として当該要素を一度削除して新たに要素をinsertすることを考えました。

    結果、属性nの順序を無視し、一番上または一番下にinsertする(insert ~ as first/last into ~)するとうまくいくのですが、他の仕様の絡みで属性nの順序は降順にしたいので

    UPDATE [dbo].[Data] SET [XML].modify('insert <elm n="2">200</elm> before (/root/elm[@n="1"])[1]')

    を実行しましたが、要素<elm n="1">に値がない(<elm n="1" />)と更新できませんでした。

    最後の手段でxml文字列を直接編集する(xmlを文字列として受け取り、要素を見つけて文字列として編集してしまう)しかないのでしょうか?


    2019年6月4日 5:35

すべての返信

  • https://stackoverflow.com/questions/3854308/xquery-adding-or-replacing-attribute-in-single-sql-update-command

    ここのように、存在してなければinsert text { 更新する値 } into ...するようなクエリを書くのはどうでしょうか?

    <念のための追記>

    存在するか確認する対象はテキストノードなので、

    .exist('/root/elm[@n=2]/text()')

    みたいなクエリになります。

    • 編集済み Hongliang 2019年6月4日 6:30
    2019年6月4日 6:26
  • Hongliang様

    ご指導ありがとうございます。
    先ずは投稿の誤りについて元の質問を修正いたしました。

    ご教示いただいた存在チェックと並行して、値をテキストノード?に持たせるのではなく、属性に持たせることも考えてみたいと思います。(大きな設計変更になってしまいますが)

    2019年6月4日 6:54
  • Hongliang様にヒントを頂いていましたが、属性に値を持たせることで目的の機能が得られたので設計を変えることにしました。

    【データ】

    テーブル名:[Data]
    XMLデータ:列名[XML]

    <root  xml:space="preserve">
        <elm n="3" value="100" /> 
         <elm n="2" value="" />
        <elm n="1" value="" />
    < /root>

    【更新するSQL文】
    UPDATE [dbo].[Data] SET [XML].modify('replace value of (/root/elm[@n="2"]/@value)[1] with "200"')

    【結果】
    <root  xml:space="preserve">
        <elm n="3" value="100" /> 
         <elm n="2" value="200" />
        <elm n="1" value="" />
    < /root>

    結果的には十分目的を達せられたのでシステム開発はこの方向に舵を切ることにしました。ありがとうございました。

    2019年6月4日 8:13