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

如何确保XML.Nodes始终返回值或关联变量至XML.Nodes表

解决SQL Server 2022中XML为空时仍返回固定字段的问题

场景与问题

从表中读取的XML结构如下:

<timecard>
  <selectby>3</selectby>
  <approvalaction>2</approvalaction>
  <approvalperiodtype>1</approvalperiodtype>
  <approvalperiodrange>3</approvalperiodrange>
  <perioddate>2024-12-16T10:41:23</perioddate>
  <operationkey>5b1f7115-09b6-4f29-8613-edbf3d1d5265</operationkey>
  <levels>e54b5a4b-c1bd-4f4d-807e-0f3810f20446</levels>
</timecard>

原查询用于解析XML并返回单条记录(@RcdSetId和@RcdType为存储过程传入变量,示例中固定赋值):

declare @Xml xml, @RcdSetID int = 1, @RcdType char(1) = 'O'

select @xml = oldxml from dbo.Audit where AuditKey = 'F033126A-01BA-4A38-AED6-73DA7ABA7F6C';

select @RcdSetID RcdSetID, @RcdType RcdType,
       isnull(cast(d.value('selectby[1]','int') as varchar(1000)),'') selectby,
       isnull(cast(d.value('approvalaction[1]','int') as varchar(1000)),'') approvalaction,
       isnull(cast(d.value('approvalperiodtype[1]','int') as varchar(1000)),'') approvalperiodtype,
       isnull(cast(d.value('approvalperiodrange[1]','int') as varchar(1000)),'') approvalperiodrange,
       isnull(cast(d.value('perioddate[1]','datetime') as varchar(1000)),'') perioddate,
       isnull(cast(d.value('operationkey[1]','varchar(36)') as varchar(1000)),'') operationkey,
       isnull(cast(d.value('levels[1]','varchar(36)') as varchar(1000)),'') levels
from @Xml.nodes('//timecard') workdays(d)

原查询在XML非空时运行正常,但当XML为空时,@Xml.nodes('//timecard')返回空集,导致整个查询无结果返回。需求是:无论XML是否包含数据,始终返回@RcdSetId和@RcdType的值;若XML有数据则返回对应字段值,若无数据则其他字段为空。

解决方案

方案一:使用LEFT JOIN确保返回单条记录

通过将查询主表设为包含单条记录的数据集,再与XML节点结果做LEFT JOIN,确保即使XML为空,主数据集仍会返回一条记录:

declare @Xml xml, @RcdSetID int = 1, @RcdType char(1) = 'O'

select @xml = oldxml from dbo.Audit where AuditKey = 'F033126A-01BA-4A38-AED6-73DA7ABA7F6C';

select 
    @RcdSetID RcdSetID, 
    @RcdType RcdType,
    isnull(cast(d.value('selectby[1]','int') as varchar(1000)),'') selectby,
    isnull(cast(d.value('approvalaction[1]','int') as varchar(1000)),'') approvalaction,
    isnull(cast(d.value('approvalperiodtype[1]','int') as varchar(1000)),'') approvalperiodtype,
    isnull(cast(d.value('approvalperiodrange[1]','int') as varchar(1000)),'') approvalperiodrange,
    isnull(cast(d.value('perioddate[1]','datetime') as varchar(1000)),'') perioddate,
    isnull(cast(d.value('operationkey[1]','varchar(36)') as varchar(1000)),'') operationkey,
    isnull(cast(d.value('levels[1]','varchar(36)') as varchar(1000)),'') levels
from (VALUES(1)) AS t(Id)
LEFT JOIN @Xml.nodes('//timecard') workdays(d) ON 1=1

方案二:直接使用XML变量的value方法

这种写法更简洁,直接通过XML变量的value方法取值,当XML为空或节点不存在时,value返回NULL,再通过ISNULL转为空字符串:

declare @Xml xml, @RcdSetID int = 1, @RcdType char(1) = 'O'

select @xml = oldxml from dbo.Audit where AuditKey = 'F033126A-01BA-4A38-AED6-73DA7ABA7F6C';

select 
    @RcdSetID RcdSetID, 
    @RcdType RcdType,
    isnull(cast(@Xml.value('(//timecard/selectby)[1]','int') as varchar(1000)),'') selectby,
    isnull(cast(@Xml.value('(//timecard/approvalaction)[1]','int') as varchar(1000)),'') approvalaction,
    isnull(cast(@Xml.value('(//timecard/approvalperiodtype)[1]','int') as varchar(1000)),'') approvalperiodtype,
    isnull(cast(@Xml.value('(//timecard/approvalperiodrange)[1]','int') as varchar(1000)),'') approvalperiodrange,
    isnull(cast(@Xml.value('(//timecard/perioddate)[1]','datetime') as varchar(1000)),'') perioddate,
    isnull(cast(@Xml.value('(//timecard/operationkey)[1]','varchar(36)') as varchar(1000)),'') operationkey,
    isnull(cast(@Xml.value('(//timecard/levels)[1]','varchar(36)') as varchar(1000)),'') levels

两种方案都能满足需求:XML有数据时返回对应字段值,XML为空时返回@RcdSetId、@RcdType及其他空字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 09:27:09