Metodo value() (tipo di dati xml)

Esegue un'espressione XQuery sul codice XML e restituisce un valore di tipo SQL, rappresentato da un valore scalare.

Questo metodo viene in genere utilizzato per estrarre un valore da un'istanza XML archiviata in una colonna, un parametro o una variabile di tipo xml. Ciò consente di specificare query SELECT che combinano o confrontano dati XML con dati di colonne non di tipo XML.

Sintassi

value (XQuery, SQLType)

Argomenti

  • XQuery
    Espressione XQuery rappresentata da un valore letterale stringa, che recupera i dati contenuti nell'istanza XML. Deve restituire almeno un valore, altrimenti verrà restituito un errore.

  • SQLType
    Tipo SQL preferito che verrà restituito, rappresentato da un valore letterale stringa. Il tipo restituito dal metodo corrisponde al parametro SQLType. SQLType non può essere un tipo di dati xml, un tipo CLR definito dall'utente o un tipo di dati image, text, ntext o sql_variant. SQLType può tuttavia essere un tipo di dati SQL definito dall'utente.

Il metodo value() utilizza l'operatore Transact-SQL CONVERT in modo implicito e tenta di convertire il risultato dell'espressione XQuery, ovvero la rappresentazione della stringa serializzata, dal tipo XSD al tipo SQL corrispondente specificato dalla conversione Transact-SQL. Per ulteriori informazioni sulle regole relative al cast del tipo per CONVERT, vedere CAST e CONVERT (Transact-SQL).

Nota

Per motivi relativi alle prestazioni, anziché utilizzare il metodo value() in un predicato per eseguire il confronto con un valore relazionale, è consigliabile utilizzare exist() con ql:column(). Questa operazione è illustrata nell'esempio D seguente.

Esempi

A. Utilizzo del metodo value() su una variabile di tipo xml

Nell'esempio seguente, un'istanza XML viene archiviata in una variabile di tipo xml. Il metodo value() recupera il valore dell'attributo ProductID dal codice XML e quindi lo assegna a una variabile int.

DECLARE @myDoc xml
DECLARE @ProdID int
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
  <Warranty>1 year parts and labor</Warranty>
  <Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
</Features>
</ProductDescription>
</Root>'

SET @ProdID =  @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int' )
SELECT @ProdID

Il risultato restituito è il valore 1.

Benché nell'istanza XML sia presente un solo attributo ProductID, in base alle regole della tipizzazione statica è necessario specificare in modo esplicito che l'espressione di percorso restituisce un singleton. Alla fine dell'espressione di percorso viene pertanto specificato [1]. Per ulteriori informazioni sulla tipizzazione statica, vedere XQuery e tipizzazione statica.

B. Utilizzo del metodo value() per recuperare un valore da una colonna di tipo xml

La query seguente viene eseguita su una colonna di tipo xml (CatalogDescription) nel database AdventureWorks2008R2. La query recupera i valori dell'attributo ProductModelID da ognuna delle istanze XML archiviate nella colonna.

SELECT CatalogDescription.value('           
    declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";           
       (/PD:ProductDescription/@ProductModelID)[1]', 'int') AS Result           
FROM Production.ProductModel           
WHERE CatalogDescription IS NOT NULL           
ORDER BY Result desc           

Dalla query precedente si noti quanto segue:

  • Viene utilizzata la parola chiave namespace per definire un prefisso dello spazio dei nomi.

  • In base ai requisiti per la tipizzazione statica, nel metodo value() viene aggiunto [1] alla fine dell'espressione di percorso, allo scopo di indicare in modo esplicito che l'espressione restituisce un singleton.

Risultato parziale:

-----------
35         
34         
...

C. Utilizzo dei metodi value() ed exist() per recuperare valori da una colonna di tipo xml

Nell'esempio seguente viene illustrato l'utilizzo del metodo value() e del metodo exist() del tipo di datixml. Il metodo value() consente di recuperare i valori dell'attributo ProductModelID dal codice XML. Il metodo exist() nella clausola WHERE consente di filtrare le righe della tabella.

La query recupera dalle istanze XML gli ID dei modelli del prodotto che includono tra le caratteristiche informazioni relative alla garanzia (elemento <Warranty>). La condizione della clausola WHERE utilizza il metodo exist() per recuperare solo le righe che soddisfano tale condizione.

SELECT CatalogDescription.value('
     declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
           (/PD:ProductDescription/@ProductModelID)[1] ', 'int') as Result
FROM  Production.ProductModel
WHERE CatalogDescription.exist('
     declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";

     /PD:ProductDescription/PD:Features/wm:Warranty ') = 1

Dalla query precedente si noti quanto segue:

  • La colonna CatalogDescription è una colonna XML tipizzata, ovvero a tale colonna è associato una raccolta di schemi. Nel prologo di una query XQuery, la dichiarazione dello spazio dei nomi consente di definire il prefisso utilizzato successivamente nel corpo della query.

  • Se il metodo exist() restituisce 1 (True), significa che l'istanza XML include l'elemento figlio <Warranty> come una delle caratteristiche.

  • Il metodo value() della clausola SELECT recupera quindi i valori dell'attributo ProductModelID come valori integer.

Risultato parziale:

Result     
-----------
19         
23         
...

D. Utilizzo del metodo exist() in sostituzione del metodo value()

Per motivi relativi alle prestazioni, anziché utilizzare il metodo value() in un predicato per eseguire il confronto con un valore relazionale, è consigliabile utilizzare exist() con sql:column(). Ad esempio:

CREATE TABLE T (c1 int, c2 varchar(10), c3 xml)
GO

SELECT c1, c2, c3 
FROM T
WHERE c3.value( '/root[1]/@a', 'integer') = c1
GO

È possibile scrivere il codice nel modo seguente:

SELECT c1, c2, c3 
FROM T
WHERE c3.exist( '/root[@a=sql:column("c1")]') = 1
GO