14

我正在尝试从具有 null 作为属性之一的 XML 中进行选择。它没有返回 null,而是返回 0。我做错了什么?
请参阅下面的代码进行复制:

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)

提前致谢。

4

8 回答 8

13

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

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

这将选择 null。顺便说一下作者代码有错别字

xmlns:xsi="http://www.w3.org/2001/XMLSchema-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)
于 2012-05-23T20:44:46.443 回答
11

我认为如果你使用 number() 函数,你会得到预期的 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) 
于 2011-01-28T21:53:51.453 回答
5

因为您将字段设置为 INT,所以 xsi:nil="true" 字段和值 0 都将最终为 0,因为 INT 的默认值是 0。

您可以先转换为 VARCHAR 以检测包含 xsi:nil="true" 的字符串字段产生的空字符串 (''),然后将结果转换为 INT。

这个 SELECT 会给你你想要的答案

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
于 2010-07-09T07:03:30.463 回答
2

我会建议这种方法:

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)
于 2013-05-20T18:39:16.807 回答
2

我只是根据需要使用 NULLIF 将空字符串转换为 NULL。

nil现在可以使用生成FOR XML,但我从来没有弄清楚如何解析它对不起......

于 2010-07-08T23:27:40.613 回答
1

一个聪明的方法是从需要空值的 XML 中删除 Property1 节点。因此,您希望在结果集中为空的任何节点都不要将其添加到 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 节点,因此它会导致一个空值

于 2014-11-07T10:25:51.500 回答
0

我不确定您的特定情况是否需要您先对节点进行子查询,但如果不是,您可以请求 .value 并提供 xPath。由于 Property1 节点存在,您想要评估 Property1 节点的 text() 而不是节点本身:

 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 语句中提供最详细的元素路径并使用“../”而不是子查询节点结果。

于 2013-05-08T19:34:45.383 回答
0

就我而言,我使用的是布尔数据类型,所以这里的所有答案都不适用于我。如果你使用的是布尔数据类型,你可以试试这个:

myXML.value('Property1[1] cast as xs:boolean?','BIT') AS Property1,

我添加了这段代码:

cast as xs:boolean?','BIT'

如果 boolean 为 null,则强制转换为 null,如果为 null,则返回 null,否则返回 1 或 0。

于 2019-03-29T16:26:57.483 回答