PAYATHON 2026

SQL Server 存储过程解析 BizTalk XML 子节点为何返回 NULL?

数据小陈

结论

子元素也带有 ns0 命名空间前缀,因此读取时,XQuery 路径也要包含该前缀;文本节点则应写作 text()。当前查询的根节点路径带有 ns0,但字段路径没有命名空间前缀,并且把 text() 写成了 text,所以没有匹配到子节点的值。

题目给出的 XML 中,MessageID、CTDateTime、VisitNo 和 AccessionNo 都属于 URI http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo 对应的命名空间。

修改存储过程

为 XML 列设置清晰的别名,并在每个子节点路径中添加 ns0::

ALTER PROCEDURE [dbo].[HHN_MohCTOrder]
    @xml XML
AS
BEGIN
    ;WITH XMLNAMESPACES (
        'http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo' AS ns0
    )
    SELECT
        n.value('(ns0:MessageID/text())[1]', 'varchar(13)') AS MessageID,
        n.value('(ns0:CTDateTime/text())[1]', 'varchar(14)') AS CTDateTime,
        n.value('(ns0:VisitNo/text())[1]', 'varchar(12)') AS VisitNo,
        n.value('(ns0:AccessionNo/text())[1]', 'varchar(12)') AS AccessionNo
    FROM @xml.nodes('/ns0:HHN_MohCTOrder') AS t(n);
END

nodes() 会将匹配到的根节点作为上下文行,n.value() 再从该节点读取相应的子元素。[1] 用来满足 value() 对单个结果的要求。此写法假设传入参数的结构与题目所示一致,且 namespace URI 与实际消息完全相同。

检查传入的 XML

如果修改后仍然读不到值,可以先查看存储过程收到的 XML:

SELECT @xml;

检查根元素、子元素名称和命名空间 URI。XML namespace 根据 URI 匹配,前缀名称可以不同;查询中声明的 ns0 只需映射到消息使用的同一 URI。如果实际 XML 使用了不同的 URI,需要相应调整 XMLNAMESPACES 声明。

备注:内容仅供参考。