【问题标题】:SQL Server: How to check child node exist or not in xml when using xquerySQL Server:使用xquery时如何检查xml中是否存在子节点
【发布时间】:2020-03-26 03:23:44
【问题描述】:

这就是我在 XML 数据中迭代并从 XML 中提取值的方式。

我的 XML

<?xml version="1.0" encoding="utf-16"?>
<Root>
  <PeriodData>
    <PeriodType>ANNUALONLY</PeriodType>
    <Period>2010 FY</Period>
  </PeriodData>
  <PeriodData>
    <PeriodType>ANNUALONLY</PeriodType>
    <Period>2011 FY</Period>
    <IsDeleted/>
  </PeriodData>
  <PeriodData>
    <PeriodType>ANNUALONLY</PeriodType>
    <Period>2011 FY</Period>
    <IsDeleted>Y</IsDeleted>
  </PeriodData>  
</Root>

我在 SP 中的代码,我通过它循环迭代并通过 xquery 从 XML 中提取数据:

DECLARE @PeriodType VARCHAR(20), @Period VARCHAR(30), @IsDeleted CHAR(1)
DECLARE @MasterID INT
DECLARE @i INT, @cnt INT = @Periods.value('count(/Root/PeriodData)', 'INT');

SET @i = 1;
WHILE @i <= @cnt BEGIN

      SELECT @PeriodType = col.value('(PeriodType/text())[1]','VARCHAR(20)')
         , @Period = col.value('(Period/text())[1]','VARCHAR(30)')
         , @IsDeleted = col.value('(IsDeleted/text())[1]','VARCHAR(30)')
      FROM @Periods.nodes('/Root/PeriodData[position() = sql:variable("@i")]') AS tab(col);

      IF NOT EXISTS (SELECT * FROM tblCalenderDetail WHERE PeriodType=@PeriodType AND Period=@Period AND IsDeleted='Y')
      BEGIN
          INSERT INTO tblCalenderDetail (MasterID,PeriodType,Period,IsDeleted)
            VALUES(@MasterID,@PeriodType,@Period,'N')
      END
      ELSE
      BEGIN
        UPDATE tblCalenderDetail SET IsDeleted='N' WHERE PeriodType=@PeriodType AND Period=@Period
      END

   SET @i += 1;
END

查看 IsDeleted 子节点不存在于第一条记录中,IsDeleted 子节点确实存在于第二行但值为空。

那么在while循环中迭代时如何检查IsDeleted子节点是否存在

我尝试了下面的代码来检查每行中是否存在 IsDeleted 节点但没有工作而是抛出错误

@IsDeleted = IIF(col.exist('//IsDeleted') , col.value('(IsDeleted/text())[1]','VARCHAR(30)') ,'N')

在循环中如果要检查IsDeleted 节点是否存在,那么它的值将存储在@IsDeleted 变量中。如果节点不存在,那么我会将 'N' 存储在 @IsDeleted 变量中。如何做到这一点?

请给我一些指导。

【问题讨论】:

    标签: sql-server tsql xquery


    【解决方案1】:

    我得到了解决方案。这个我用ISNULL(col.value('(IsDeleted/text())[1]','VARCHAR(30)'), 'N')

    完整的工作代码

    declare @xml xml=N'<?xml version="1.0" encoding="utf-16"?>
    <Root>
      <PeriodData>
        <PeriodType>ANNUALONLY</PeriodType>
        <Period>2010 FY</Period>
      </PeriodData>
      <PeriodData>
        <PeriodType>ANNUALONLY</PeriodType>
        <Period>2011 FY</Period>
        <IsDeleted/>
      </PeriodData>
      <PeriodData>
        <PeriodType>ANNUALONLY</PeriodType>
        <Period>2011 FY</Period>
        <IsDeleted>Y</IsDeleted>
      </PeriodData>  
    </Root>'
    
    DECLARE @PeriodType VARCHAR(20), @Period VARCHAR(30), @IsDeleted CHAR(1)
            DECLARE @MasterID INT
            DECLARE @i INT, @cnt INT = @xml.value('count(/Root/PeriodData)', 'INT');
    
            SET @i = 1;
            WHILE @i <= @cnt BEGIN
    
    
                  SELECT @PeriodType = col.value('(PeriodType/text())[1]','VARCHAR(20)')
                     , @Period = col.value('(Period/text())[1]','VARCHAR(30)')
                     , @IsDeleted = ISNULL(col.value('(IsDeleted/text())[1]','VARCHAR(30)'), 'N')
                  FROM @xml.nodes('/Root/PeriodData[position() = sql:variable("@i")]') AS tab(col);
    
                  PRINT @PeriodType + ' '+@Period+' '+@IsDeleted
    
               SET @i += 1;
            END
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多