【问题标题】:SQL XML .node .query() returns empty string instead of NULL if table node exist如果表节点存在,SQL XML .node .query() 返回空字符串而不是 NULL
【发布时间】:2019-06-29 00:54:29
【问题描述】:

如果表不存在,为什么 .query() 返回空字符串而不是 NULL?我是在 SQL 中查询 xml 的新手,所以我只是在玩,这是出乎意料的。

这是一个问题的例子。

declare @xml xml

set @xml = N'<xdoc><Header><OrderID>1234</OrderID><Detail><ProductID>12345</ProductID><Amount>12.50</Amount></Detail></Header></xdoc>'

SELECT  
    Tbl.Col.value('OrderID[1]', 'varchar(10)') as OrderID,  
    Tbl.Col.query('Detail') as Detail
FROM @xml.nodes('//Header') Tbl(Col)

set @xml = N'<xdoc><Header><OrderID>1234</OrderID></Header></xdoc>'

SELECT  
    Tbl.Col.value('OrderID[1]', 'varchar(10)') as OrderID,  
    Tbl.Col.query('Detail') as Detail
FROM @xml.nodes('//Header') Tbl(Col)

第一个 select 语句按预期返回。 Detail 字段是表头中表详细信息的 xml。

但是,在第二个 select 语句中,此标头记录没有明细表,因此我希望该字段为 null 而不是空字符串。

Output

【问题讨论】:

  • XML 支持高度特定于供应商 - 所以请添加标签以指定您是否使用mysqlpostgresqlsql-serveroracledb2 - 或完全不同的东西。
  • query 方法通常实现 [a part of] XQuery 规范 w3.org/TR/xquery-31 没有 null 的概念。该方法仅在应用于 null sql xml 值(sql server)时才返回 null。

标签: sql sql-server xml xml-parsing


【解决方案1】:

你想要的都是可能的,但你必须有一点不同的想法。在 XML 中,值 NULL缺失节点 指示。

此外,“价值”这个词在这句话中非常重要。如果您要查找的元素不存在,.value() 方法将返回 NULL.query()-方法在任何情况下都会返回一个 XML 类型的片段。

XML 由节点组成。元素(任何&lt;SomeElement&gt; 以及所有嵌套节点)是一种特殊的节点。元素中的浮动文本本身就是一个节点。看看这些例子:

你的 XML

declare @xml xml

set @xml = 
N'<xdoc>
  <Header>
    <OrderID>1234</OrderID>
    <Detail>
      <ProductID>12345</ProductID>
      <Amount>12.50</Amount>
    </Detail>
  </Header>
</xdoc>'

--.query()可以返回&lt;Detail&gt;-fragment

SELECT @xml.query('/xdoc/Header/Detail');

<Detail>
  <ProductID>12345</ProductID>
  <Amount>12.50</Amount>
</Detail>

--该节点不存在。你得到的不是一个NULL-value,而是一个空的XML节点

SELECT @xml.query('/xdoc/Header/Dummy');                                       --<-- empty XML

--现在看.value()

SELECT @xml.value('(/xdoc/Header/Dummy)[1]','nvarchar(100)');                  --<-- NULL
SELECT @xml.value('(/xdoc/Header/Detail)[1]','nvarchar(100)');                 --<-- 1234512.50
SELECT @xml.value('(/xdoc/Header/Detail/text())[1]','nvarchar(100)');          --<-- NULL
SELECT @xml.value('(/xdoc/Header/Detail/ProductID)[1]','nvarchar(100)');       --<-- 12345
SELECT @xml.value('(/xdoc/Header/Detail/ProductID/text())[1]','nvarchar(100)');--<-- 12345

第一个电话是明确的,没有&lt;Dummy&gt;,因此,我们得到了一个NULL
第二个电话可能会让你大吃一惊。 元素中的所有内容。在这种情况下,我们得到所有值的组合。您可能已经将此视为模拟 group_concat() 的技巧。
第三次调用返回NULL,因为&lt;Detail&gt; 中没有text()
...第四次和第五次调用返回相同,但最后一个带有text() 的调用最为具体,因此是最佳选择。

这取决于您的需求、您想要查询的内容以及您想要返回的内容。此外,您可以使用 empty(SomeNode)not(empty(SomeNode)) 等谓词在 XPath 中使用 XQuery 过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2014-07-28
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    相关资源
    最近更新 更多