2012-06-21 47 views
3

我有一個SQL Server 2008數據庫與值如以下簡化的例子的XML列:測試針對特定節點值在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()來匹配特定文本或空節點?除了可讀性之外,還有什麼理由關心嗎?當有人指出我錯過的任何明顯的事情時,我期待着即將面臨的挑戰。 :)

回答

8

在空元素上調用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 
+0

提示facepalm! :)我可以發誓我試過[。= sql:variable]表單,但我猜不是。像魅力一樣工作 - 謝謝! –

+0

對於這樣的事情如何:http://stackoverflow.com/questions/33130499/how-to-replace-text-if-it-exists-otherwise-add-text-to-a-xml-node-using- SQL – Si8