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 的所有记录。但是,我尝试了 query
和 exist
的不同示例,但似乎无法正确查询。这是我正在尝试的当前版本,但它没有返回我预期的结果:
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
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 的所有记录。但是,我尝试了 query
和 exist
的不同示例,但似乎无法正确查询。这是我正在尝试的当前版本,但它没有返回我预期的结果:
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