2011-12-11 143 views
5

我必須使用exist()value()方法,在SQL Server 2008中SQL Server中的XML存在()

我的XML看起來像這樣一些問題:

<?xml version="1.0" encoding="UTF-8"?> 
<library> 
    <branches> 
     <branch> 
      <codelib>1</codelib> 
      <name>Campus</name> 
     </branch> 
     <branch> 
      <codelib>2</codelib> 
      <name>47th</name> 
     </branch> 
     <branch> 
      <codelib>3</codelib> 
      <name>Mall</name> 
     </branch>    
    </branches> 
    <books> 
     <book type="SF"> 
      <codb>11</codb> 
      <title>Robots</title> 
      <authors> 
       <author>author1 robots</author> 
       <author>author2 robots</author> 
      </authors> 
      <price>10</price> 
      <stocks> 
       <branch codelib="1" amount="10"/> 
       <branch codelib="2" amount="5"/> 
       <branch codelib="4" amount="15"/> 
      </stocks> 
      <from>20</from> 
      <to>30</to> 
     </book> 
     <book type="poetry"> 
      <codb>12</codb> 
      <title>Poetry book</title> 
      <authors> 
       <author>AuthorPoetry</author> 
      </authors> 
      <price>14</price> 
      <stocks> 
       <branch codelib="1" amount="7"/> 
       <branch codelib="2" amount="5"/> 
      </stocks> 
      <from>25</from> 
      <to>40</to> 
     </book>  
     <book type="children"> 
      <codb>19</codb> 
      <title>Faitytales</title> 
      <authors>    
       <author>AuthorChildren</author>    
      </authors> 
      <price>20</price> 
      <stocks> 
       <branch codelib="1" amount="10"/> 
       <branch codelib="3" amount="55"/> 
       <branch codelib="4" amount="15"/> 
      </stocks> 
      <from>70</from> 
      <to>75</to> 
     </book>  
     <book type="literature"> 
      <codb>19</codb> 
      <title>T</title> 
      <authors> 
       <author>A</author>     
      </authors> 
      <price>17</price> 
      <stocks> 
       <branch codelib="1" amount="40"/> 
      </stocks> 
      <from>85</from> 
      <to>110</to> 
     </book> 
    </books> 
</library> 

鑑於這種XML,我必須寫SELECT子句將使用query(),value()exist()各2次,最小值。我甚至不能在相同的SELECT中使用query()exist(),因爲看來WHERE子句沒有任何影響。

例如,我要檢索的所有<branch>元素是書的類型SF的孩子,但select語句

declare @genre varchar(15) 
    set @genre = 'SF' 
    SELECT XMLData.query('//branch') from TableA 
    WHERE XMLData.exist('//book[./@type = sql:variable("@genre")]') = 1 

檢索所有<branch>元素,而不僅僅是從目標的那些書。我無法弄清楚我的選擇有什麼問題。另外,我很感激query()exist()value()在相同的選擇(是否有可能嵌套在SQL XML select語句?)

回答

7

那麼,在這裏你的XPath表達式是「罪魁禍首」一個小例子:

query('//branch') 

這是說:選擇從整個文件全部<branch>節點。它只是做你說的要做的事情,真的......

這個查詢有什麼問題?

SELECT 
    XMLData.query('/library/books/book[@type=sql:variable("@genre")]//branch') 
FROM dbo.TableA 

這將檢索所有<branch>子節點爲具有type="SF"作爲一個屬性<book>節點....

什麼是你想與你的query()exist()value()全部實現在同一語句??很可能,它可以做得更容易....

另外:我認爲你誤解了SQL Server XQuery中的.exist()。如果你有你在這裏的講話:

SELECT (some columns) 
FROM dbo.TableA 
WHERE XMLData.exist('//book[@type = sql:variable("@genre")]') = 1 

你基本上是告訴SQL Server從dbo.TableA檢索所有行存儲在XMLData的XML包含一個<book type=.....>節點 - 應用 - 你是從表中選擇行XMLData列的內容的選擇...

+0

這不是我想要的,但我必須在同一個語句中同時使用query(),value()和exist()。這就是爲什麼我想做一些像T-SQL,SELECT ... WHERE ...那樣的過濾,如果可能的話,可能會像嵌套的SELECT語句那樣。我只想要一個關於如何實現這樣的示例的示例 – joanna

3

您提供的XML不適用於exist語句。如果你有多個XML語句並且需要找到它包含一些值的那個,那麼這個語句就會更加相關。

您提供的where子句只檢查條件是否存在,如果存在,則選擇所有branches元素,而不僅僅是條件爲真的元素。 例如,下面的(顯然)不返回任何東西:

SELECT @xmldata.query('//branch') from TableA 
WHERE @xmldata.exist('//book[./@type = "BLAH"]') = 1 

但這裏是東西給你看可以使用一個所有三個select語句。

SELECT T.c.query('./title').value('.', 'varchar(250)') as title, 
     T.c.exist('.[@type eq "SF"]') as IsSF 
    from @xmldata.nodes('//book') T(c) 
+0

您提供的SELECT接近我需要的tnx。最後一個問題......是否有可能像SELECT ... WHERE x =(SELECT..WHERE),這樣我可以使用value(),exist()和query()2次?基本上,選擇(所有3個功能)將過濾一些值,然後另一個使用過濾節點? – joanna

0

道歉,如果這是遲來的,但我只是剛剛看到這篇文章。

使用交叉應用運算符過濾到所需節點,然後從返回的節點中選擇查詢,使用XML進行過濾效率更高。要查詢子節點,您還需要包含根。在這種情況下查詢所以//分支而不是//分支。

declare @genre varchar(15) = 'SF' 
select l.query('.//branch') from TableA 
cross apply XmlData.nodes('library/books/book[@type=sql:variable("@genre")]') n (l) 

,您仍然可以添加,如果你希望存在的條款,但這實際上會增加額外的不必要的開銷

WHERE XMLData.exist('//book[./@type = sql:variable("@genre")]') = 1 

希望這有助於。 D