簡體   English   中英

使用SQL Server上另一個XML的節點更新XML列

[英]Update XML column with nodes from another XML on SQL Server

我有兩個具有1-M關系的表,兩個表都包含XML列。 我必須從第一個表的XML節點的另一個節點更新第二個表的列中的XML。 在努力學習語法之后,我終於能夠讓它發揮作用了。 但是,它仍然無法正常工作。 我在消息選項卡中看到行已更新,但是當我從第二個表中選擇值時,不會更新任何內容。 以下是我的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>

以下是子表的兩種可能模式:

<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

不完全是答案,因為我的代碼開始沒有任何問題。 我終於能夠看到子表XML列的XML模式,並且在某些行中,它在XML中有一些名稱空間。 添加命名空間后,我能夠更新數據。

WITH XMLNAMESPACES (DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9') 
UPDATE ...

然而,這仍然無法解釋為什么我得到“x行更新”但實際數據沒有變化。 此外,並非每個行都有名稱空間。 這意味着應該更新沒有名稱空間的行。 無論如何,感謝@GriGrim和@Roman Pekar的輸入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM