2010-07-08 6 views
11

Я пытаюсь выбрать из XML, который имеет нуль как один из атрибутов. Вместо того, чтобы возвращать null, он возвращает 0. Что я делаю неправильно?
См ниже код для репликации:Выбор нулевого значения из XML в SQL Server

declare @a xml 
select @a = '<TestSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instace"> 
    <Element> 
    <Property1>1</Property1> 
    <Property2>1</Property2> 
    </Element> 
    <Element> 
    <Property1 xsi:nil="true" /> 
    <Property2>2</Property2> 
    </Element> 
    <Element> 
    <Property1>3</Property1> 
    <Property2>3</Property2> 
    </Element> 
</TestSet>' 

select ParamValues.TaskChainerTask.query('Property1').value('.','int') as Property1, 
     ParamValues.TaskChainerTask.query('Property2').value('.','int') as Property2 
    from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 

возвращается:

Property1 Property2 
1   1 
0   2 
3   3 

Это возвращает то же самое:

declare @a xml 
select @a = '<TestSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instace"> 
    <Element> 
    <Property1>1</Property1> 
    <Property2>1</Property2> 
    </Element> 
    <Element> 
    <Property1 xsi:nil="true" /> 
    <Property2>2</Property2> 
    </Element> 
    <Element> 
    <Property1>3</Property1> 
    <Property2>3</Property2> 
    </Element> 
</TestSet>' 

select ParamValues.TaskChainerTask.query('Property1').value('.','int') as Property1, 
     ParamValues.TaskChainerTask.query('Property2').value('.','int') as Property2 
    from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 

Спасибо заранее.

ответ

2

Я просто использовал NULLIF, чтобы по очереди пустые строки в NULL.

Вы можете создать nil сейчас, используя FOR XML, но я никогда не работал, как разобрать его жаль ...

3

Поскольку вы устанавливаете поля для INT у вас есть проблема, что и XSI: ноль =» true ", а значение 0 будет равным 0 в качестве значения по умолчанию для INT Is.

Сначала вы можете преобразовать в VARCHAR, чтобы обнаружить пустую строку (''), которые строковые поля содержат xsi: nil =" true «производят, а затем преобразуют результат в INT.

Это ВЫБРАТЬ даст вам ответ вы после

SELECT CONVERT(INT,NULLIF(ParamValues.TaskChainerTask.query('Property1').value('.', 'varchar(5)'),'')) AS Property1 
     , CONVERT(INT,NULLIF(ParamValues.TaskChainerTask.query('Property2').value('.', 'varchar(5)'),'')) AS Property2 
FROM @a.nodes('(/TestSet/Element)') AS ParamValues (TaskChainerTask) 

В результате это дает вам:

Property1 Property2 
1   1 
NULL  2 
3   3 
10

Я думаю, что если вы используете функцию номер(), вы получите null как ожидалось. Это работает только для числовых типов, хотя:

select 
    ParamValues.TaskChainerTask.query('Property1').value('number(.)','int') as Property1,   
    ParamValues.TaskChainerTask.query('Property2').value('number(.)','int') as Property2 
from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 
10

http://go4answers.webhost4life.com/Example/including-null-columns-empty-elements-125474.aspx

[not(@xsi:nil = "true")] 

Это подберет нуль. По коду пути автора опечатки

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instace" 

экземпляра с ошибками, как instace

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

Рабочего версию автора кода

declare @a xml 
      select @a = '<TestSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
       <Element> 
       <Property1>1</Property1> 
       <Property2>1</Property2> 
       </Element> 
       <Element> 
       <Property1 xsi:nil="true" /> 
       <Property2>2</Property2> 
       </Element> 
       <Element> 
       <Property1>3</Property1> 
       <Property2>3</Property2> 
       </Element> 
      </TestSet>' 

      select ParamValues.TaskChainerTask.value('./Property1[1][not(@xsi:nil = "true")]','int') as Property1, 
        ParamValues.TaskChainerTask.value('./Property2[1][not(@xsi:nil = "true")]','int') as Property2 
       from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 
0

Я не уверен, если ваш конкретный случай требует сначала запрашивать узлы, но если вы не можете запросить значение. и предоставить xPath. Поскольку узел property1 существует, вы хотите, чтобы оценить текст() узла property1, а не сам узел:

select ParamValues.TaskChainerTask.value('Property1[1]/text()[1]','int') as Property1, 
     ParamValues.TaskChainerTask.value('Property2[1]/text()[1]','int') as Property2 

    from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 

Кроме того, чтобы убедиться, что это работает в других случаях вы можете обеспечить наиболее точный путь элемента в @ a.nodes xPath statment и подходите к «../», а не подпросите результаты узла.

1

Я бы sugest этот подход:

DECLARE @a XML = '<TestSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instace"> 
    <Element> 
    <Property1>1</Property1> 
    <Property2>1</Property2> 
    </Element> 
    <Element> 
    <Property1 xsi:nil="true" /> 
    <Property2>2</Property2> 
    </Element> 
    <Element> 
    <Property1>3</Property1> 
    <Property2>3</Property2> 
    </Element> 
</TestSet>' 

SELECT 
    ParamValues.TaskChainerTask 
     .value('./Property1[not(./@*[local-name()="nil"] = "true")][1]', 'int') as Property1, 
    ParamValues.TaskChainerTask 
     .value('./Property2[not(./@*[local-name()="nil"] = "true")][1]', 'int') as Property2 
FROM @a.nodes('//Element') ParamValues(TaskChainerTask) 
1

Умный способ сделать это было бы удалить узел property1 из XML, где нулевые значения желательны. Итак, какой бы узел ни был нулевым в вашем результирующем наборе, просто не добавляйте его в XML. Таким образом вам не придется добавлять атрибут xsi: nill.

Так Ниже будет также привести в нуль:

declare @a xml 
select @a = '<TestSet> 
    <Element> 
    <Property1>1</Property1> 
    <Property2>1</Property2> 
    </Element> 
    <Element> 
    //I have removed the property1 node and this will result in a null value 
    <Property2>2</Property2> 
    </Element> 
    <Element> 
    <Property1>3</Property1> 
    <Property2>3</Property2> 
    </Element> 
</TestSet>' 

select ParamValues.TaskChainerTask.value('./Property1[1]','int') as Property1, 
     ParamValues.TaskChainerTask.value('./Property2[1]','int') as Property2 
    from @a.nodes('(/TestSet/Element)') as ParamValues(TaskChainerTask) 

Это можно увидеть в приведенном выше примере, что нет property1 узла, следовательно, это приведет к нулевому значению

Смежные вопросы