3

1-M の関係を持つ 2 つのテーブルがあり、どちらにも XML 列が含まれています。最初のテーブルの XML ノードの別のノードから 2 番目のテーブルの列の XML を更新する必要があります。構文に苦労して動作させた後、ようやく動作させることができました。ただし、まだ機能していません。[メッセージ] タブで行が更新されているのがわかりますが、2 番目のテーブルから値を選択しても何も更新されません。これが私の TSQL コードのサンプルです。

DECLARE @Table1 TABLE (
    Id BIGINT PRIMARY KEY
    ,Document XML
    ,NewValue NVARCHAR(max)
    )

INSERT INTO @Table1
SELECT TOP 10 a.Id
    ,a.Document
    ,a.Document.value('(/root/metadata/name)[1]', 'nvarchar(500)') + 'blahblah'
FROM dbo.ParentTable a
ORDER BY a.Id DESC

DECLARE @Table2 TABLE (
    Id BIGINT PRIMARY KEY
    ,ParentId BIGINT
    ,OriginalXml XML
    ,ModifiedXml XML
    ,ValueType NVARCHAR(255)
    )

INSERT INTO @Table2
SELECT sm.Id
    ,sm.ParentId
    ,sm.MapXml
    ,sm.MapXml
    ,sm.ValueType
FROM dbo.ChildTable sm

PRINT 'before update'

UPDATE sm
SET ModifiedXml.modify('replace value of (//url/loc/text())[1] with sql:column("NewValue")')
FROM @Table2 sm
INNER JOIN @Table1 a ON a.Id = sm.ParentId
WHERE sm.ValueType = 'web';

UPDATE sm
SET ModifiedXml.modify('replace value of (/html/url/text())[1] with sql:column("NewValue")')
FROM @Table2 sm
INNER JOIN @Table1 a ON a.Id = sm.ParentId
WHERE sm.ValueType = 'html';

PRINT 'after update'

SELECT *
FROM @Table2

明確でない場合のために、親テーブルの XML スキーマを次に示します。

<root>
    <metadata>
        <title></title>
        <header></header>
        <nodeN></nodeN>
    </metadata>
</root>

そして、子テーブルの可能なスキーマは次の 2 つです。

<url>
    <loc>somevalue</loc>
</url>

<html>
    <url>somevlaue</url>
</html>

私が以前直面していた問題は、変更した XML 列を XML として宣言していたことでした。また、選択中に親テーブルから子ノードを取得していませんでしたが、代わりに更新時に値を取得しようとしていました。

アップデート

更新された SQL は次のとおりです。これは何らかの理由で機能しています。元の XML スキーマを投稿しなかった唯一の理由は、それらが長すぎるためです。元の TSQL の XPath を再確認します。

DECLARE @Table1 TABLE (
    Id BIGINT PRIMARY KEY
    ,Document XML
    ,NewValue NVARCHAR(max)
    )

INSERT INTO @Table1 (
    Id
    ,Document
    )
VALUES (
    1
    ,'<root><metadata><title>title 1</title><header>header 1</header></metadata></root>'
    )

INSERT INTO @Table1 (
    Id
    ,Document
    )
VALUES (
    2
    ,'<root><metadata><title>title 2</title><header>header 2</header></metadata></root>'
    )

INSERT INTO @Table1 (
    Id
    ,Document
    )
VALUES (
    3
    ,'<root><metadata><title>title 3</title><header>header 3</header></metadata></root>'
    )

INSERT INTO @Table1 (
    Id
    ,Document
    )
VALUES (
    4
    ,'<root><metadata><title>title 4</title><header>header 4</header></metadata></root>'
    )

UPDATE @Table1
SET NewValue = Document.value('(/root/metadata/title)[1]', 'nvarchar(max)')

DECLARE @Table2 TABLE (
    Id BIGINT PRIMARY KEY
    ,ParentId BIGINT
    ,OriginalXml XML
    ,ModifiedXml XML
    ,ValueType NVARCHAR(255)
    )

INSERT INTO @Table2
VALUES (
    1
    ,1
    ,'<url><loc>old title 1</loc></url>'
    ,'<url><loc>old title 1</loc></url>'
    ,'web'
    )

INSERT INTO @Table2
VALUES (
    2
    ,3
    ,'<html><url>old title 3</url></html>'
    ,'<html><url>old title 3</url></html>'
    ,'html'
    )

PRINT 'before update'

UPDATE sm
SET ModifiedXml.modify('replace value of (//url/loc/text())[1] with sql:column("NewValue")')
FROM @Table2 sm
INNER JOIN @Table1 a ON a.Id = sm.ParentId
WHERE sm.ValueType = 'web';

UPDATE sm
SET ModifiedXml.modify('replace value of (/html/url/text())[1] with sql:column("NewValue")')
FROM @Table2 sm
INNER JOIN @Table1 a ON a.Id = sm.ParentId
WHERE sm.ValueType = 'html';

PRINT 'after update'

SELECT *
FROM @Table2
4

1 に答える 1