Предотвращение синтаксического анализа пустых тегов XML - PullRequest
0 голосов
/ 17 мая 2019

У меня есть параметр XML с таким пустым тегом, как этот.

<dietTypes><dietType><dietaryID></dietaryID></dietType></dietTypes>

Я пытаюсь проанализировать его как целое число в хранимой процедуре,

DECLARE @MemDietTypes TABLE(DietaryID INT);
INSERT INTO @MemDietTypes
SELECT  DietTypes.Col.value('dietaryID[1]', 'INT')
FROM   @DietaryTypeXML.nodes('//dietType') DietTypes(Col);

Вышеанализируется как ноль, что проблематично для меня.Как я могу предотвратить это?Спасибо

Ответы [ 3 ]

2 голосов
/ 27 мая 2019

Попробуйте, чтобы понять неявные значения по умолчанию:

SELECT CAST(NULL AS INT)
      ,CAST('' AS INT)
      ,CAST('      ' AS INT); 

A NULL остается неизменным, но пусто по умолчанию обнуляется.Это спроектированное поведение.

Теперь вернемся к вашей проблеме:

DECLARE @DietaryTypeXML XML='<dietTypes>
                               <dietType>
                                 <dietaryID></dietaryID> <!-- This is empty -->
                               </dietType>
                             </dietTypes>';

- Движок получает пустое значение и по умолчанию обнуляет его.
- Если вы используетеvarchar Вместо этого вы получите пробел, но вам придется иметь дело со строковыми числами.

SELECT  DietTypes.Col.value('dietaryID[1]', 'INT') AS Empty_in_INT_is_implicitly_taken_as_zero
       ,DietTypes.Col.value('dietaryID[1]', 'VARCHAR(100)') AS Empty_in_VARCHAR_is_implicitly_taken_as_empty_string
FROM   @DietaryTypeXML.nodes('//dietType') DietTypes(Col);

- Предлагаемое мной решение:

SELECT  DietTypes.Col.value('dietaryID[1] cast as xs:int?', 'INT') 
FROM   @DietaryTypeXML.nodes('//dietType') DietTypes(Col);

ИспользованиеXQuery cast as xs:int? сообщает движку, что данное значение имеет значение null.Теперь возвращаемое значение больше не пусто , но NULL .

1 голос
/ 27 мая 2019

Вы можете использовать text() функция:

declare @data xml = '
    <dietTypes><dietType><dietaryID></dietaryID></dietType><dietType><dietaryID>2</dietaryID></dietType></dietTypes>';

select
    t.c.value('(dietaryID/text())[1]', 'int')
from @data.nodes('//dietType') as t(c);

возвращает:

dietaryID
-----------
NULL
2
0 голосов
/ 17 мая 2019

enter image description here Вам необходимо изменить тип данных DietaryID на varchar ()

declare @xml xml='<dietTypes>
<dietType>
<dietaryID></dietaryID>
</dietType>
</dietTypes>'

DECLARE @MemDietTypes TABLE(DietaryID varchar(10));
INSERT INTO @MemDietTypes
SELECT  DietTypes.Col.value('dietaryID[1]', 'VARCHAR(10)')
FROM   @xml.nodes('//dietTypes/dietType') DietTypes(Col);

select * from @MemDietTypes
...