Condividi tramite


Espressioni SequenceType (XQuery)

Si applica a: SQL Server

In XQuery un valore è sempre una sequenza. Il tipo del valore viene definito tipo di sequenza. Il tipo di sequenza può essere usato in un'istanza dell'espressione XQuery. La sintassi SequenceType descritta nella specifica XQuery viene utilizzata quando è necessario fare riferimento a un tipo in un'espressione XQuery.

Il nome del tipo atomico può essere usato anche nel cast come espressione XQuery. In SQL Server l'istanza di e il cast come espressioni XQuery in SequenceTypes sono parzialmente supportati.

Operatore instance of

L'istanza dell'operatore può essere usata per determinare il tipo dinamico o di runtime del valore dell'espressione specificata. Ad esempio:

  
Expression instance of SequenceType[Occurrence indicator]  

Si noti che l'operatore instance of , , Occurrence indicatorspecifica la cardinalità, il numero di elementi nella sequenza risultante. Se non viene specificato, si presuppone una cardinalità 1. In SQL Server è supportato solo l'indicatore di occorrenza punto interrogativo (?). L'indicatore di occorrenza ? indica che Expression può restituire zero o un elemento. Se viene specificato l'indicatore di occorrenza ?, restituisce True quando il Expression tipo corrisponde all'oggetto specificatoSequenceType, instance of indipendentemente dal fatto che Expression restituisca un singleton o una sequenza vuota.

Se l'indicatore dell'occorrenza ? non viene specificato, sequence of restituisce True solo quando il Expression tipo corrisponde all'oggetto Type specificato e Expression restituisce un singleton.

Nota Gli indicatori di occorrenza del segno più (+) e dell'asterisco (*) non sono supportati in SQL Server.

Negli esempi seguenti viene illustrato l'uso dell'istanza dell'operatore XQuery.

Esempio A

Nell'esempio seguente viene creata una variabile di tipo xml e viene specificata una query su di essa. L'espressione di query specifica un operatore instance of per determinare se il tipo dinamico del valore restituito dal primo operando corrisponde al tipo specificato nel secondo operando.

La query seguente restituisce True, perché il valore 125 è un'istanza del tipo specificato, xs:integer:

declare @x xml  
set @x=''  
select @x.query('125 instance of xs:integer')  
go  

La query seguente restituisce True, poiché il valore restituito dall'espressione /a[1] nel primo operando è un elemento:

declare @x xml  
set @x='<a>1</a>'  
select @x.query('/a[1] instance of element()')  
go  

Allo stesso modo, instance of restituisce True nella query seguente poiché il tipo di valore dell'espressione nella prima espressione è un attributo:

declare @x xml  
set @x='<a attr1="x">1</a>'  
select @x.query('/a[1]/@attr1 instance of attribute()')  
go  

Nell'esempio seguente, l'espressione data(/a[1] restituisce un valore atomico tipizzato come xdt:untypedAtomic. Tramite l'operatore instance of viene pertanto restituito True.

declare @x xml  
set @x='<a>1</a>'  
select @x.query('data(/a[1]) instance of xdt:untypedAtomic')  
go  

Nella query seguente, l'espressione data(/a[1]/@attrA restituisce un valore atomico non tipizzato. Tramite l'operatore instance of viene pertanto restituito True.

declare @x xml  
set @x='<a attrA="X">1</a>'  
select @x.query('data(/a[1]/@attrA) instance of xdt:untypedAtomic')  
go  

Esempio B

In questo esempio viene eseguita una query su una colonna XML tipizzata del database di esempio AdventureWorks. La raccolta di XML Schema associata alla colonna sulla quale viene eseguita la query fornisce le informazioni di tipizzazione.

Nell'espressione data () restituisce il valore tipizzato dell'attributo ProductModelID il cui tipo è xs:string in base allo schema associato alla colonna. Tramite l'operatore instance of viene pertanto restituito True.

SELECT CatalogDescription.query('  
   declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";  
   data(/PD:ProductDescription[1]/@ProductModelID) instance of xs:string  
') as Result  
FROM Production.ProductModel  
WHERE ProductModelID = 19  

Per altre informazioni, vedere Confrontare dati XML tipizzati con dati XML non tipizzati.

Le query seguenti usano l'espressione booleana instance of per determinare se l'attributo LocationID è di tipo xs:integer:

SELECT Instructions.query('  
   declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
   /AWMI:root[1]/AWMI:Location[1]/@LocationID instance of attribute(LocationID,xs:integer)  
') as Result  
FROM Production.ProductModel  
WHERE ProductModelID=7  

La query seguente viene specificata sulla colonna XML tipizzata CatalogDescription. Le informazioni di tipizzazione sono fornite dalla raccolta di XML Schema associata alla colonna.

Nella query viene utilizzato il test element(ElementName, ElementType?) nell'espressione instance of per verificare che tramite /PD:ProductDescription[1] venga restituito un nodo di elemento con un nome e un tipo specifici.

SELECT CatalogDescription.query('  
     declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";  
     /PD:ProductDescription[1] instance of element(PD:ProductDescription, PD:ProductDescription?)  
    ') as Result  
FROM  Production.ProductModel  
where ProductModelID=19  

La query restituisce True.

Esempio C

Quando si usano tipi di unione, l'espressione instance of in SQL Server presenta una limitazione: in particolare, quando il tipo di un elemento o di un attributo è un tipo di unione, instance of potrebbe non determinare il tipo esatto. Di conseguenza, una query restituirà False, a meno che i tipi atomici utilizzati in SequenceType siano l'elemento padre di livello più alto del tipo effettivo dell'espressione nella gerarchia simpleType, ovvero che i tipi atomici specificati in SequenceType siano figli diretti di anySimpleType. Per informazioni sulla gerarchia dei tipi, vedere Regole di cast dei tipi in XQuery.

La prossima query esegue le operazioni seguenti:

  • Crea a una raccolta di XML Schema contenente la definizione di un tipo unione, ad esempio un tipo integer o stringa.

  • Dichiarare una variabile xml tipizzata utilizzando la raccolta di XML Schema.

  • Assegna un'istanza XML di esempio alla variabile.

  • Esegue una query sulla variabile per illustrare il funzionamento di instance of quando è applicato a un tipo unione.

Query:

CREATE XML SCHEMA COLLECTION MyTestSchema AS '  
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ns" xmlns:ns="http://ns">  
<simpleType name="MyUnionType">  
<union memberTypes="integer string"/>  
</simpleType>  
<element name="TestElement" type="ns:MyUnionType"/>  
</schema>'  
Go  

La query seguente restituisce False, perché il SequenceType specificato nell'espressione instance of non è l'elemento padre di livello più alto del tipo effettivo dell'espressione specificata. Ovvero, il valore di <TestElement> è un tipo integer. L'elemento padre di livello più alto è xs:decimal, ma non è specificato come secondo operando dell'operatore instance of.

SET QUOTED_IDENTIFIER ON  
DECLARE @var XML(MyTestSchema)  
  
SET @var = '<TestElement xmlns="http://ns">123</TestElement>'  
  
SELECT @var.query('declare namespace ns="http://ns"   
   data(/ns:TestElement[1]) instance of xs:integer')  
go  

Poiché l'elemento padre di livello più alto di xs:integer è xs:decimal, se viene modificata specificando xs:decimal come SequenceType la query restituirà True.

SET QUOTED_IDENTIFIER ON  
DECLARE @var XML(MyTestSchema)  
SET @var = '<TestElement xmlns="http://ns">123</TestElement>'  
SELECT @var.query('declare namespace ns="http://ns"     
   data(/ns:TestElement[1]) instance of xs:decimal')  
go  

Esempio D

In questo esempio si crea prima di tutto una raccolta di XML Schema e la si usa per digitare una variabile xml . Viene quindi eseguita una query sulla variabile xml tipizzata per illustrare la instance of funzionalità.

La raccolta di XML Schema seguente definisce un tipo semplice, myType e un elemento, <root>, di tipo myType:

drop xml schema collection SC  
go  
CREATE XML SCHEMA COLLECTION SC AS '  
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="myNS" xmlns:ns="myNS"  
xmlns:s="https://schemas.microsoft.com/sqlserver/2004/sqltypes">  
      <import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes"/>  
      <simpleType name="myType">  
           <restriction base="s:varchar">  
                  <maxLength value="20"/>  
            </restriction>  
      </simpleType>  
      <element name="root" type="ns:myType"/>  
</schema>'  
Go  

Creare ora una variabile xml tipizzata ed eseguirne una query:

DECLARE @var XML(SC)  
SET @var = '<root xmlns="myNS">My data</root>'  
SELECT @var.query('declare namespace sqltypes = "https://schemas.microsoft.com/sqlserver/2004/sqltypes";  
declare namespace ns="myNS";   
   data(/ns:root[1]) instance of ns:myType')  
go  

Poiché il tipo myType deriva per restrizione da un tipo varchar definito nello schema sqltypes, anche instance of restituirà True.

DECLARE @var XML(SC)  
SET @var = '<root xmlns="myNS">My data</root>'  
SELECT @var.query('declare namespace sqltypes = "https://schemas.microsoft.com/sqlserver/2004/sqltypes";  
declare namespace ns="myNS";   
data(/ns:root[1]) instance of sqltypes:varchar?')  
go  

Esempio E

Nell'esempio seguente, l'espressione recupera uno dei valori dell'attributo IDREFS e utilizza instance of per determinare se il valore sia di tipo IDREF. Nell'esempio vengono eseguite le operazioni seguenti:

  • Crea una raccolta di XML Schema in cui l'elemento ha un attributo di tipo OrderList IDREFS e l'elemento <Order> ha un attributo di tipo OrderID ID.<Customer>

  • Crea una variabile xml tipizzata e assegna a essa un'istanza XML di esempio.

  • Specifica una query sulla variabile. L'espressione di query recupera il primo valore ID ordine dall'attributo di tipo OrderList IDRERS del primo <Customer>oggetto . Il valore recuperato è di tipo IDREF. L'operatore instance of pertanto restituisce True.

create xml schema collection SC as  
'<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:Customers="Customers" targetNamespace="Customers">  
            <element name="Customers" type="Customers:CustomersType"/>  
            <complexType name="CustomersType">  
                        <sequence>  
                            <element name="Customer" type="Customers:CustomerType" minOccurs="0" maxOccurs="unbounded" />  
                        </sequence>  
            </complexType>  
             <complexType name="OrderType">  
                <sequence minOccurs="0" maxOccurs="unbounded">  
                            <choice>  
                                <element name="OrderValue" type="integer" minOccurs="0" maxOccurs="unbounded"/>  
                            </choice>  
                </sequence>                                             
                <attribute name="OrderID" type="ID" />  
            </complexType>  
  
            <complexType name="CustomerType">  
                <sequence minOccurs="0" maxOccurs="unbounded">  
                            <choice>  
                                <element name="spouse" type="string" minOccurs="0" maxOccurs="unbounded"/>  
                                <element name="Order" type="Customers:OrderType" minOccurs="0" maxOccurs="unbounded"/>  
                            </choice>  
                </sequence>                                             
                <attribute name="CustomerID" type="string" />  
                <attribute name="OrderList" type="IDREFS" />  
            </complexType>  
 </schema>'  
go  
declare @x xml(SC)  
set @x='<CustOrders:Customers xmlns:CustOrders="Customers">  
                <Customer CustomerID="C1" OrderList="OrderA OrderB"  >  
                              <spouse>Jenny</spouse>  
                                <Order OrderID="OrderA"><OrderValue>11</OrderValue></Order>  
                                <Order OrderID="OrderB"><OrderValue>22</OrderValue></Order>  
  
                </Customer>  
                <Customer CustomerID="C2" OrderList="OrderC OrderD" >  
                                <spouse>John</spouse>  
                                <Order OrderID="OrderC"><OrderValue>33</OrderValue></Order>  
                                <Order OrderID="OrderD"><OrderValue>44</OrderValue></Order>  
  
                        </Customer>  
                <Customer CustomerID="C3"  OrderList="OrderE OrderF" >  
                                <spouse>Jane</spouse>  
                                <Order OrderID="OrderE"><OrderValue>55</OrderValue></Order>  
                                <Order OrderID="OrderF"><OrderValue>55</OrderValue></Order>  
                </Customer>  
                <Customer CustomerID="C4"  OrderList="OrderG"  >  
                                <spouse>Tim</spouse>  
                                <Order OrderID="OrderG"><OrderValue>66</OrderValue></Order>  
                        </Customer>  
                <Customer CustomerID="C5"  >  
                </Customer>  
                <Customer CustomerID="C6" >  
                </Customer>  
                <Customer CustomerID="C7"  >  
                </Customer>  
</CustOrders:Customers>'  
  
select @x.query(' declare namespace CustOrders="Customers";   
 data(CustOrders:Customers/Customer[1]/@OrderList)[1] instance of xs:IDREF ? ') as XML_result  

Limitazioni di implementazione

Limitazioni:

  • I tipi di sequenza schema-element() e schema-attribute() non sono supportati per il confronto con l'operatore instance of .

  • Le sequenze complete, ad esempio (1,2) instance of xs:integer*, non sono supportate.

  • Quando si usa una forma del tipo di sequenza element() che specifica un nome di tipo, ad esempio element(ElementName, TypeName), il tipo deve essere qualificato con un punto interrogativo (?). Ad esempio, element(Title, xs:string?) indica che l'elemento potrebbe essere null. SQL Server non supporta il rilevamento in fase di esecuzione della proprietà xsi:nil tramite instance of.

  • Se il valore in Expression proviene da un elemento o da un attributo tipizzato come unione, SQL Server può identificare solo la primitiva, non derivata, tipo da cui è stato derivato il tipo del valore. Ad esempio, se <e1> è definito per avere un tipo statico di (xs:integer | xs:string), il codice seguente restituirà False.

    data(<e1>123</e1>) instance of xs:integer  
    

    data(<e1>123</e1>) instance of xs:decimal tuttavia restituirà True.

  • Per i tipi di sequenza processing-instruction() e document-node(), sono consentiti solo moduli senza argomenti. Ad esempio, processing-instruction() è consentito, ma processing-instruction('abc') non è consentito.

Operatore cast as

Il cast come espressione può essere usato per convertire un valore in un tipo di dati specifico. Ad esempio:

  
Expression cast as  AtomicType?  

In SQL Server il punto interrogativo (?) è necessario dopo .AtomicType Ad esempio, come illustrato nella query seguente, "2" cast as xs:integer? converte il valore stringa in un numero intero:

declare @x xml  
set @x=''  
select @x.query('"2" cast as xs:integer?')  

Nella query seguente data() restituisce il valore tipizzato dell'attributo ProductModelID, un tipo stringa. L'operatore cast asconverte il valore in xs:integer.

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS PD)  
SELECT CatalogDescription.query('  
   data(/PD:ProductDescription[1]/@ProductModelID) cast as xs:integer?  
') as Result  
FROM Production.ProductModel  
WHERE ProductModelID = 19  

L'uso esplicito di data() non è necessario in questa query. L'espressione cast as esegue l'atomizzazione implicita sull'espressione di input.

Funzioni costruttore

È possibile utilizzare le funzioni costruttore del tipo atomico. Ad esempio, anziché usare l'operatore cast as , "2" cast as xs:integer?è possibile usare la funzione del costruttore xs:integer(), come nell'esempio seguente:

declare @x xml  
set @x=''  
select @x.query('xs:integer("2")')  

L'esempio seguente restituisce un valore xs:date uguale a 2000-01-01Z.

declare @x xml  
set @x=''  
select @x.query('xs:date("2000-01-01Z")')  

È inoltre possibile utilizzare i costruttori per i tipi atomici definiti dall'utente. Ad esempio, se la raccolta di XML Schema associata al tipo di dati XML definisce un tipo semplice, è possibile utilizzare un costruttore myType() per restituire un valore di tale tipo.

Limitazioni di implementazione

  • Le espressioni XQuery typeswitch, castable e treat non sono supportate.

  • cast come richiede un punto interrogativo (?) dopo il tipo atomico.

  • xs:QName non è supportato come tipo per il cast. Usare invece expanded-QName .

  • xs:date, xs:time e xs:datetime richiedono un fuso orario, indicato da una Z.

    La query seguente ha esito negativo, perché il fuso orario non è specificato.

    DECLARE @var XML  
    SET @var = ''  
    SELECT @var.query(' <a>{xs:date("2002-05-25")}</a>')  
    go  
    

    Aggiungendo l'indicatore di fuso orario Z al valore, la query riesce.

    DECLARE @var XML  
    SET @var = ''  
    SELECT @var.query(' <a>{xs:date("2002-05-25Z")}</a>')  
    go  
    

    Risultato:

    <a>2002-05-25Z</a>  
    

Vedi anche

Espressioni XQuery
Sistema di tipi (XQuery)