【问题标题】:Test for a specific node value in an XML column including potentially empty nodes测试 XML 列中的特定节点值,包括可能为空的节点
【发布时间】:2012-06-21 22:22:33
【问题描述】:

我在 SQL Server 2008 数据库中有一个 XML 列,其值类似于以下简化示例:

案例 1

<root>
    <child>sometimes text here</child>
    <otherstuff ..... />
</root>

案例 2

<root>
    <child/>
    <otherstuff ..... />
</root>

给定一个字符串值,我希望能够在“子”节点中选择具有特定值的行,包括选择案例 2。

例如,如果我有一个局部变量:

declare @queryText nvarchar(MAX)
select @queryText = 'sometimes text here'

我可以通过以下方式选择与案例 1 匹配的行:

select * from [my_table] 
where [my_xml_column].exist('/root/child[text()=sql:variable("@queryText")]') = 1

但是,对于案例 2,我希望 @queryText = '' 或 @queryText = NULL 能够正常工作,但两者都不匹配。

作为一种解决方法,我可以使用:

select * from [my_table]
where [my_xml_column].value('(/root/child)[1], 'nvarchar(MAX)') = @queryText

这行得通,但它让我觉得我错过了一些东西并使用肮脏的解决方法来测试是否存在 .value() 而不是 .exist()... 是否有类似的表达我可以 [并且应该?] 在 .exist() 中使用以匹配特定文本或空节点?除了可读性之外,还有什么理由关心吗?当有人指出我错过的任何明显明显的事情时,我期待着我即将到来的面。 :)

【问题讨论】:

    标签: sql-server xml xquery-sql


    【解决方案1】:

    在空元素上调用 text() 会导致 NULL 而不是空字符串。因此,在这两种情况下,通过 @queryText = '' 或 @queryText = NULL 将永远不会等于 NULL。请记住,没有什么等于 NULL,甚至 NULL。

    请参阅下面的示例,该示例说明如何使用 exist 进行填充或空搜索。

    declare @my_table table (i int, my_xml_column xml)
    insert into @my_table
        select 1, '<root><child>sometimes text here</child><otherstuff /></root>' union all
        select 2, '<root><child/><otherstuff/></root>'
    
    declare @queryText varchar(100) = '';
    
    select  *, 
            [using_text()]=[my_xml_column].value('(/root/child/text())[1]', 'varchar(max)'),
            [using_path]=[my_xml_column].value('(/root/child)[1]', 'varchar(max)')
    from    @my_table
    
    select  *
    from    @my_table
    where   [my_xml_column].exist('/root/child[.= sql:variable("@queryText")]') = 1
    

    【讨论】:

    猜你喜欢
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多