SQL XML查询/存在:查找空值/非空值

时间:2018-03-09 15:33:56

标签: sql sql-server xml sqlxml

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行,这些行都采用此格式。如果我在查询的1部分中将0更改为AND,它会返回记录,但我认为这是错误的(根据解释的页面) exist函数,0表示不存在)。所以,我很困惑。

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

2 个答案:

答案 0 :(得分:0)

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

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;

答案 1 :(得分: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