【问题标题】:Update XML node value based on a match from XML type column根据 XML 类型列的匹配更新 XML 节点值
【发布时间】:2021-02-18 17:42:08
【问题描述】:

我有一个带有 XML 列的 SQL 表。

表结构是

CREATE TABLE [dbo].[UserSettings](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [UserID] [int] NOT NULL,    
    [UserName] [varchar](100) NULL, 
    [Setting] [xml] NULL,   
    [CreateDate] [datetime] NOT NULL
)

设置 xml 列如下所示:

<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserID>1</UserID>
  <Reports>
        <string>Report - 1</string>
        <string>Report - 2</string>
        <string>Report - 3</string>
        <string>Report - 4</string>
  </Reports>
</UserSettings>

我想将&lt;Reports&gt;中的报告-1更新为报告-一,报告-2更新为报告-二

另外,如果有一个值 Report - 4 那么我想从&lt;Reports&gt;中删除它

所以我在列中的最终结果应该是这样的:

<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserID>1</UserID>
  <Reports>
        <string>Report - One</string>
        <string>Report - Two</string>
        <string>Report - Three</string>     
  </Reports>
</UserSettings>

编辑: 我已经尝试过 REPLACE 方法。我不确定这是否是最有效的方法。

update UserSettings
set Setting=REPLACE(convert(varchar(max),Setting),'<string>Report - 1</string>','<string>Report - One</string>')
where convert(varchar(max),Setting) like '%<string>Report - 1</string>%'

编辑: 我读到了modify() method,但报告的顺序可以是任何顺序。我无法让我的查询使用它。

【问题讨论】:

  • 你试过什么?你在哪里卡住了?
  • 您阅读过modify() method 文档吗?

标签: sql sql-server xml tsql


【解决方案1】:

简单的方法是使用替换作为字符串,但是如果您不想在任何地方替换该值(例如在&lt;Reports&gt; 标记之外),则此方法无用

-- to update report 1 to 3 ( I just did it for 1):
update UserSettings
set Setting = replace(cast(Setting as nvarchar(max)) , '<string>Report - 1</string>','<string>Report - one</string>')

-- to remove report 4 
update UserSettings
set Setting = replace(cast(Setting as nvarchar(max)) , '<string>Report - 4</string>','')

【讨论】:

    【解决方案2】:

    您可以尝试不同的方法。

    可以通过 XQuery 及其 FLWOR 表达式动态组合 XML,而不是查找和替换,即修改。

    SQL

    -- DDL and sample data population, start
    DECLARE @UserSettings TABLE (
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [UserID] [int] NOT NULL,    
        [UserName] [varchar](100) NULL, 
        [Setting] [xml] NULL,   
        [CreateDate] [datetime] NOT NULL
    );
    INSERT INTO @UserSettings (UserID, UserName, Setting, CreateDate)
    VALUES
    (0, 'John', N'<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <UserID>1</UserID>
        <Reports>
            <string>Report - 1</string>
            <string>Report - 2</string>
            <string>Report - 3</string>
            <string>Report - 4</string>
        </Reports>
    </UserSettings>', 
        GETDATE()
    );
    -- DDL and sample data population, end
    
    UPDATE @UserSettings
    SET Setting = Setting.query('<UserSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    {
        for $x in /UserSettings/*[local-name()!="Reports"]
        return $x,
            element Reports {
                for $y in ("One","Two","Three")
                return <string>{concat("Report - ", $y)}</string>
            }
    }
    </UserSettings>');
    
    -- test
    SELECT * FROM @UserSettings;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      • 2019-10-25
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      • 2017-01-03
      • 2019-12-01
      相关资源
      最近更新 更多