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

SQL Server XML列节点更新:类型错误与动态XPath问题及解决

SQL Server中更新XML列指定节点值的问题与解决方案

环境与数据结构

1. 表结构

CREATE TABLE [dbo].[STA11]
(   
    [ID_STA11] [dbo].[int] NOT NULL,    
    [COD_ARTICU] [varchar](15) NOT NULL,        
    [CAMPOS_ADICIONALES] [xml](CONTENT [dbo].[CAMPOS_ADICIONALES_STA11]) NULL
    
 CONSTRAINT [PK_STA11] PRIMARY KEY CLUSTERED 
(
    [ID_STA11] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

2. XML Schema集合

CREATE XML SCHEMA COLLECTION [dbo].[CAMPOS_ADICIONALES_STA11] AS 
N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="CAMPOS_ADICIONALES">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:all>
                        <xsd:element name="CA_TAG" type="CA_TAG_schemeType" minOccurs="0" nillable="true"/>
                    </xsd:all>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
    <xsd:simpleType name="CA_TAG_schemeType">
        <xsd:restriction base="xsd:string">
            <xsd:maxLength value="999"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>'
GO

3. 存储的XML数据

<CAMPOS_ADICIONALES>
  <CA_TAG></CA_TAG>
</CAMPOS_ADICIONALES>

首次更新尝试与错误

尝试使用modify()方法更新<CA_TAG>节点值:

UPDATE STA11
SET CAMPOS_ADICIONALES.modify('
  replace value of (/CAMPOS_ADICIONALES/CA_TAG/text())[1]
  with sql:variable(&quot;@ValorCampoAdicional&quot;)
')
WHERE COD_ARTICU = '0100100129';

触发错误:

Error: Msg 9312, Level 16, State 1, Line 6

XQuery [STA11.CAMPOS_ADICIONALES.modify()]: 'text()' is not supported on simple typed or 'http://www.w3.org/2001/XMLSchema#anyType' elements, found 'element(CA_TAG,CA_TAG_schemeType) *'.

另一种写法同样报错:

UPDATE [STA11]
SET CAMPOS_ADICIONALES.modify('
    replace value of (/CAMPOS_ADICIONALES/CA_TAG)[1]/text()[1]
    with &quot;basura&quot;
')
WHERE [COD_ARTICU] = '0100100129'

错误信息:

Error: Msg 9312, Level 16, State 1, Line 31
XQuery [STA11.CAMPOS_ADICIONALES.modify()]: 'text()' is not supported on simple typed or 'http://www.w3.org/2001/XMLSchema#anyType' elements, found 'element(CA_TAG,CA_TAG_schemeType) ?'.

固定节点的正确更新方案

通过类型转换实现固定节点的更新:

DECLARE @ValorCampoAdicional VARCHAR(100) = 'Hello there';
UPDATE dbo.STA11
    SET CAMPOS_ADICIONALES.modify('
      replace value of (/CAMPOS_ADICIONALES/CA_TAG)[1]
      with sql:variable(&quot;@ValorCampoAdicional&quot;) cast as CA_TAG_schemeType?
    ')
    WHERE COD_ARTICU = '0100100129';

动态指定节点名的问题

尝试动态指定要更新的节点名时,两种方式均失败:

方式一:字符串拼接XPath

DECLARE @ValorCampoAdicional VARCHAR(100) = 'Hello there';
DECLARE @CampoAdicional VARCHAR(100) = 'CA_TAG';

UPDATE dbo.STA11
SET CAMPOS_ADICIONALES.modify('
  replace value of (/CAMPOS_ADICIONALES/' + @CampoAdicional + ')[1]
  with sql:variable(&quot;@ValorCampoAdicional&quot;) cast as CA_TAG_schemeType?
')
WHERE COD_ARTICU = '0100100129';

错误:

Msg 8172, Level 16, State 1, Line 5
The argument 1 of the XML data type method "modify" must be a string literal.

方式二:使用sql:variable()传入节点名

DECLARE @ValorCampoAdicional VARCHAR(100) = 'Hello there';
DECLARE @CampoAdicional VARCHAR(100) = 'CA_TAG';

UPDATE dbo.STA11
SET CAMPOS_ADICIONALES.modify('
  replace value of (/CAMPOS_ADICIONALES/sql:variable(&quot;@CampoAdicional&quot;))[1]
  with sql:variable(&quot;@ValorCampoAdicional&quot;) cast as CA_TAG_schemeType?
')
WHERE COD_ARTICU = '0100100129';

错误:

Msg 9335, Level 16, State 1, Line 6
XQuery [dbo.STA11.CAMPOS_ADICIONALES.modify()]: The XQuery syntax '/function()' is not supported.

最终解决方案

创建用户定义函数fn_SetearCampoAdicional,通过字符串替换结合XML查询实现动态节点更新:

IF (OBJECT_ID('fn_SetearCampoAdicional','FN') IS NOT NULL) DROP FUNCTION fn_SetearCampoAdicional
GO
CREATE FUNCTION fn_SetearCampoAdicional(
    @dataXML XML,
    @CampoAdicional VARCHAR(999),
    @ValorCampoAdicional VARCHAR(999)
)
RETURNS XML
AS
BEGIN    

    DECLARE @tagApertura varchar(999)
    DECLARE @tagCierre varchar(999)
    DECLARE @xmlInsert AS XML 
    DECLARE @resultado AS XML

    set @tagApertura = '&lt;' + @CAMPOADICIONAL+ '&gt;'
    set @tagCierre = '&lt;/' + @CAMPOADICIONAL+ '&gt;'

    set @xmlInsert = @tagApertura + @ValorCampoAdicional + @tagCierre

    set @resultado = (select CAST(REPLACE(CAST(@dataXML AS NVARCHAR(MAX))
                               ,CAST(@dataXML.query('/CAMPOS_ADICIONALES/*[local-name(.) eq sql:variable(&quot;@CampoAdicional&quot;)][1]') AS NVARCHAR(MAX))
                               ,CAST(@xmlInsert AS NVARCHAR(MAX)))AS XML))

    RETURN @resultado
END;
GO

内容的提问来源于stack exchange,提问作者Rodrigo Fulanito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:37:06