2011-12-11 16 views
5

Ho alcuni problemi con i exist() e value() metodi in SQL Server 2008.SQL Server XML esistere()

mio XML è simile al seguente:

<?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> 

Detto questo XML, devo scrivere un SELECT clausola che utilizzerà query(), value() e exist() 2 volte ciascuno, minimo. Non riesco nemmeno a utilizzare query() e exist() nello stesso SELECT, in quanto sembra che la clausola WHERE non abbia alcun effetto.

Per esempio, voglio recuperare tutti i <branch> elementi che sono figli del libro con il tipo SF, ma l'istruzione select

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

recupera tutti gli <branch> elementi, non solo quelli del bersaglio libro. Non riesco a capire cosa c'è che non va nella mia selezione. Inoltre, gradirei un piccolo esempio con query(), exist() e value() nella stessa selezione (è possibile avere nidificato select in xml sql?)

risposta

7

Bene, la vostra espressione XPath qui è il "colpevole":

query('//branch') 

Questo dice: selezionare tutti i<branch> nodi dall'intero documento. Sta solo facendo quello che stai dicendo di fare, davvero ....

Cosa c'è di sbagliato in questa domanda qui ??

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

Che sarebbe recuperare tutti i <branch> sottonodi per il nodo <book> che ha type="SF" come attributo ....

Cosa stai cercando di raggiungere con il vostro query(), exist() e value() tutte nella stessa istruzione ?? Molto probabilmente, può essere fatto molto più facile ...

Inoltre: Penso che stai interpretando erroneamente ciò che fa .exist() in SQL Server XQuery. Se avete la vostra dichiarazione qui:

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

si sta fondamentalmente dicendo SQL Server per recuperare tutte le righe dalla dbo.TableA dove l'XML memorizzato in XMLData contiene un nodo <book type=.....> - si sta selezionando le righe della tabella - NON applicando una selezione per il contenuto della colonna XMLData ...

+0

Non è quello che voglio, ma devo usare sia query(), value() ed exist() nella stessa istruzione. Ecco perché voglio fare un qualche tipo di filtraggio come in T-SQL, SELECT ... DOVE ... può qualcosa di simile alle istruzioni SELECT nidificate se è possibile. Voglio solo un esempio su come ottenere smth come quello – joanna

3

L'XML che hai fornito non si presta a una dichiarazione exist. Se avessi più istruzioni XML e avessi bisogno di trovare quello in cui conteneva qualche valore, allora l'affermazione sarebbe stata più rilevante.

La clausola where fornita dall'utente verifica solo se la condizione esiste e, in caso affermativo, seleziona tutti gli elementi branches, non solo quelli in cui la condizione è vera. Ad esempio, il seguente (ovviamente) non restituisce nulla:

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

Ma qui è qualcosa da mostrare è possibile utilizzare tutti e tre in una 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

Il SELECT che hai fornito è vicino a quello che mi serve, tnx. Un ultimo problema ... è possibile avere qualcosa come SELECT ... WHERE x = (SELECT..WHERE), così posso usare value(), exist() e query() 2 volte? Fondamentalmente, una selezione (con tutte e 3 le funzioni) che filtra alcuni valori, e poi un'altra che usa i nodi filtrati? – joanna

0

Mi scuso se è arrivato tardi ma ho appena visto questo post.

È più efficiente con XML filtrare utilizzando l'operatore cross apply per filtrare sul nodo richiesto, quindi selezionare la query dai nodi restituiti. Per interrogare i nodi figli è necessario includere anche la radice. nella query quindi in questo caso .//branch anziché // branch.

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

È possibile aggiungere ancora la clausola esiste, se si vuole, ma questo sarà effettivamente aggiungere ulteriore inutile sovraccarico

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

Spero che questo aiuti. D

Problemi correlati