SQL XML Query/Exist: 寻找 null/not 空值

SQL XML Query/Exist: Looking for null/not null values

SQL 服务器 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>

在这个 table 中,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;

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

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

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

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;

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