SQL Сервер: как проверить наличие или отсутствие дочернего узла в xml при использовании xquery - PullRequest
0 голосов
/ 25 марта 2020

Это то, как я перебираю данные XML и извлекаю значение из XML.

My 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, с помощью которого я перехожу в l oop и извлечение данных из XML с помощью xquery:

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 дочерний узел делает существует во 2-й строке, но имеет нулевое значение.

Итак, как я могу проверить IsDeleted дочерний узел существует или нет при итерации, пока l oop?

Я пытался этот код ниже, чтобы проверить, существует ли узел IsDeleted в каждой строке, но он не работал, скорее выдает ошибку .

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

В l oop, если хотите проверить, существует ли IsDeleted узел тогда его значение будет сохранено в переменной @IsDeleted. Если узел не существует, я буду хранить 'N' в переменной @IsDeleted . Как этого добиться?

Пожалуйста, дайте мне руководство.

1 Ответ

0 голосов
/ 25 марта 2020

Я получил решение. это я использовал 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
...