【问题标题】:SQL XML Query/Exist: Looking for null/not null valuesSQL XML 查询/存在:寻找空值/非空值
【发布时间】:2018-03-09 15:33:56
【问题描述】:

SQL Server 2016
Field1 (XML(.), null)

示例数据:

<ProcessPositionOpening xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.hr-xml.org/3">
    <ApplicationArea xmlns="http://www.openapplications.org/oagis/9">
        ...
    </ApplicationArea>
    <DataArea>
        <Process xmlns="http://www.openapplications.org/oagis/9">
            ...
        </Process>
        <PositionOpening>
            <DocumentID />
            <PositionRequester>
                ...
            </PositionRequester>
            <PositionProfile>
                ...
                <PositionFormattedDescription>
                    <ID>...</ID>
                    <Content />
                </PositionFormattedDescription>
                ...
            </PositionProfile>
        </PositionOpening>
    </DataArea>
</ProcessPositionOpening>

在此表中,Field1 设置为 XML,我一直在尝试查找节点 Content 可能不为 NULL 的所有记录。但是,我尝试了 queryexist 的不同示例,但似乎无法正确查询。这是我正在尝试的当前一个,但它没有返回我所期望的:

SELECT  *
FROM    Table1
WHERE   Field1.value('(/ProcessPositionOpening/DataArea/PositionOpening/PositionProfile/PositionFormattedDescription/Content)[1]','varchar(50)') <> ''
    AND Message = 'Request Received';

我也试过了:

SELECT  *
FROM    Table1
WHERE   Message = 'Request Received'
    AND Field1.exist('/ProcessPositionOpening') = 1;

我尝试了上面的查询,只是想看看查询的基本设置是否可行。它不返回任何记录。如果我删除查询的AND 部分,我在这个表中有超过 19,000 行都是这种格式的。如果我在查询的AND 部分将1 更改为0,它会返回记录,但我觉得这是错误的(基于解释exist 函数的页面,0 表示不存在) .所以,我很困惑。

我想找到Content 节点有值的所有记录,同样找到Content 没有值的所有记录。任何帮助都非常感谢。谢谢!

【问题讨论】:

  • 提示:你的 XML 有命名空间。更糟糕的是:有不同的 default 命名空间。您可以正确声明它们(阅读WITH XMLNAMESPACES),也可以使用通配符(/*:root/*:content)省略它们...
  • @Shnugo - 这似乎奏效了。我正在尝试使用您的答案,但仍然没有得到任何结果。在文本中添加*: 即可。

标签: sql sql-server xml sqlxml


【解决方案1】:

我希望以下提供一些模板来解决这个问题:

DECLARE @mockup TABLE(Descr VARCHAR(100),theXML XML);
INSERT INTO @mockup VALUES
 ('<content> exists with value','<root><content>blah</content></root>' )
,('<content> exists without value','<root><content></content></root>' ) --semantically the same as self-closed...
,('<content> exists self-closed','<root><content/></root>' )
,('<content> does not exist','<root></root>' );

--Find a Content with value
SELECT * FROM @mockup
WHERE theXML.exist('/root/content/text()')=1;

--Find a Content with or without value
SELECT * FROM @mockup
WHERE theXML.exist('/root/content')=1;

--Find a Content without value
SELECT * FROM @mockup
WHERE theXML.exist('/root/content[empty(text())]')=1;

--Find rows with no content
SELECT * FROM @mockup
WHERE theXML.exist('/root/content')=0;

【讨论】:

    【解决方案2】:

    xml.exist 函数对我来说并不直观,我已经 经常使用它失败。即使文档清楚地说明了如何使用它:https://docs.microsoft.com/en-us/sql/t-sql/xml/exist-method-xml-data-type?view=sql-server-ver15

    但是事先阅读文档对我来说也不直观 :)

    DECLARE @mockup TABLE(Descr VARCHAR(100),theXML XML);
    INSERT INTO @mockup VALUES
     ('<content> exists with value','<root><content>blah</content></root>' )
    ,('<content> exists without value','<root><content></content></root>' ) --semantically the same as self-closed...
    ,('<content> exists self-closed','<root><content/></root>' )
    ,('<content> does not exist','<root></root>' )
    ,('XML is null', NULL );
    SELECT *, theXML.exist('/root/content') FROM @mockup
    

    给予

    <content> exists with value <root><content>blah</content></root>    1
    <content> exists without value  <root><content /></root>    1
    <content> exists self-closed    <root><content /></root>    1
    <content> does not exist    <root />    0
    XML is null NULL    NULL
    

    所以我总是将条件包装在 ISNULL(..,..)

    SELECT *, ISNULL(theXML.exist('/root/content'),0) FROM @mockup
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2022-01-01
      • 2021-12-03
      相关资源
      最近更新 更多