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 indicator
specifica 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'operatoreinstance 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 tramiteinstance 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, maprocessing-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 as
converte 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>