You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server中XML列参数键值的查询与更新问题

问题描述

我有一个名为Rules的表,包含numeric类型的RuleID列和XML类型的XMLData列。以下是RuleID = 1时XMLData的内容:

<EP Name="C3EPIC" ReturnVar="AUTOMDWG">
    <Parameters>
        <Parameter Key="Server" Value='="Rules.MyRules.com"'
                   Description="Server"/>
        <Parameter Key="EPICLIBRARY" Value='="DEVPGM10"' Description="Library"/>
        <Parameter Key="Library" Value='="DEVPGM10"' Description=""/>
        <Parameter Key="ProgramName" Value='="MyProgram"' Description=""/>
        <Parameter Key="Function" Value="=HDWEFUNCA"
                   Description="Hardware MFG MODEL #"/>
        <Parameter Key="Trim" Value="=HDWETRIMA" Description="Hardware Trim"/>
    </Parameters>
    <OutputVariables/>
</EP>

我的两个任务:

  1. 找出所有参数键EPICLIBRARY值为="DEVPGM10"的RuleID;
  2. 将这些规则中的DEVPGM10修改为QAPGM10。

我尝试了以下查询XML的代码:

DECLARE @xml XML = (SELECT XMLData
                    FROM Rules 
                    WHERE ruleid = 1   
                    FOR XML AUTO, ELEMENTS, ROOT('TopLevel'))

SELECT
    epic.value('@key', 'nvarchar(255)') as AttrKey,    
    epic.value('@value', 'nvarchar(255)') as AttrVal  
FROM
    @xml.nodes('TopLevel/Rules/XMLData/EP/Parameters/Parameter') A(epic)

该代码返回6行,但所有记录的AttrKey和AttrVal均为NULL,我期望得到对应的键值列表,恳请提供指导。


解决方案

1. 修复查询返回NULL的问题

你的查询返回NULL有两个核心原因:

  • 用FOR XML AUTO, ELEMENTS, ROOT('TopLevel')包装XMLData列时,会把原XML内容转为嵌套结构的文本节点,而非可解析的XML节点,导致XPath无法定位;
  • XPath属性名区分大小写,你XML中用的是Key/Value(首字母大写),但查询里写的是小写@key/@value。

直接读取XMLData列即可正确查询:

SELECT
    epic.value('@Key', 'nvarchar(255)') as AttrKey,    
    epic.value('@Value', 'nvarchar(255)') as AttrVal  
FROM
    Rules
CROSS APPLY
    XMLData.nodes('/EP/Parameters/Parameter') A(epic)
WHERE
    RuleID = 1;

2. 任务1:筛选符合条件的RuleID

使用XML的exist()方法直接过滤符合参数条件的记录:

SELECT RuleID
FROM Rules
WHERE
    XMLData.exist('/EP/Parameters/Parameter[@Key="EPICLIBRARY" and @Value=''"DEVPGM10"''']') = 1;

注:SQL中字符串内的单引号需要用双单引号转义,因此属性值里的双引号需要写成'"DEVPGM10"'。

3. 任务2:更新XML中的目标值

使用XML的modify()方法结合replace value of语句更新属性值:

-- 仅更新EPICLIBRARY参数
UPDATE Rules
SET XMLData.modify('
    replace value of (/EP/Parameters/Parameter[@Key="EPICLIBRARY"]/@Value)[1]
    with '"QAPGM10"'
')
WHERE
    XMLData.exist('/EP/Parameters/Parameter[@Key="EPICLIBRARY" and @Value=''"DEVPGM10"''']') = 1;

-- 同时更新EPICLIBRARY和Library参数
UPDATE Rules
SET XMLData.modify('
    replace value of (/EP/Parameters/Parameter[@Key="EPICLIBRARY"]/@Value)[1] with '"QAPGM10"';
    replace value of (/EP/Parameters/Parameter[@Key="Library"]/@Value)[1] with '"QAPGM10"'
')
WHERE
    XMLData.exist('/EP/Parameters/Parameter[@Key="EPICLIBRARY" and @Value=''"DEVPGM10"''']') = 1;

内容的提问来源于stack exchange,提问作者Rich Kenyon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:52:43