Expresiones SequenceType (XQuery)
Se aplica a:SQL Server
En XQuery, un valor siempre es una secuencia. Se hace referencia a los tipos de valor como tipos de secuencia. El tipo de secuencia se puede usar en una instancia de expresión XQuery. La sintaxis SequenceType descrita en la especificación de XQuery se utiliza cuando se debe hacer referencia a un tipo de una expresión XQuery.
El nombre del tipo atómico también se puede usar en la conversión como expresión XQuery. En SQL Server, la instancia de y la conversión como expresiones XQuery en SequenceTypes se admiten parcialmente.
Operador instance of
La instancia del operador se puede usar para determinar el tipo dinámico o en tiempo de ejecución del valor de la expresión especificada. Por ejemplo:
Expression instance of SequenceType[Occurrence indicator]
Tenga en cuenta que el instance of
operador , Occurrence indicator
especifica la cardinalidad, el número de elementos de la secuencia resultante. Si no se especifica esto, se supone que la cardinalidad es 1. En SQL Server, solo se admite el indicador de repetición de signo de interrogación (?). El indicador de repetición ? indica que Expression
puede devolver cero o un elemento. Si se especifica el indicador de repetición ? , instance of
devuelve True cuando el tipo coincide con el Expression
especificado SequenceType
, independientemente de si Expression
devuelve un singleton o una secuencia vacía.
Si no se especifica el indicador de repetición ? , sequence of
devuelve True solo cuando el Expression
tipo coincide con el Type
especificado y Expression
devuelve un singleton.
Nota No se admiten los indicadores de repetición del símbolo más (+) y el asterisco (*) en SQL Server.
En los ejemplos siguientes se muestra el uso de lainstancia del operador XQuery.
Ejemplo A
En el ejemplo siguiente se crea una variable de tipo xml y se especifica una consulta en ella. La expresión de consulta especifica un operador instance of
para determinar si el tipo dinámico del valor devuelto por el primer operando coincide con el tipo especificado en el segundo operando.
La consulta siguiente devuelve True, porque el valor 125 es una instancia del tipo especificado, xs:integer:
declare @x xml
set @x=''
select @x.query('125 instance of xs:integer')
go
La consulta siguiente devuelve True, pues el valor devuelto por la expresión, /a[1], del primer operando es un elemento:
declare @x xml
set @x='<a>1</a>'
select @x.query('/a[1] instance of element()')
go
De forma similar, instance of
devuelve True en la consulta siguiente, porque el tipo de valor de la primera expresión es un atributo:
declare @x xml
set @x='<a attr1="x">1</a>'
select @x.query('/a[1]/@attr1 instance of attribute()')
go
En el ejemplo siguiente, la expresión, data(/a[1]
, devuelve un valor atómico con el tipo xdt:untypedAtomic. Por lo tanto, devuelve instance of
True.
declare @x xml
set @x='<a>1</a>'
select @x.query('data(/a[1]) instance of xdt:untypedAtomic')
go
En la consulta siguiente, la expresión, data(/a[1]/@attrA
, devuelve un valor atómico sin tipo. Por lo tanto, devuelve instance of
True.
declare @x xml
set @x='<a attrA="X">1</a>'
select @x.query('data(/a[1]/@attrA) instance of xdt:untypedAtomic')
go
Ejemplo B
En este ejemplo, se consulta una columna con el tipo XML de la base de datos de ejemplo AdventureWorks. La colección de esquemas XML asociada con la columna que se consulta proporciona la información de escritura.
En la expresión, data() devuelve el valor con tipo del atributo ProductModelID cuyo tipo es xs:string según el esquema asociado a la columna. Por lo tanto, devuelve instance of
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
Para obtener más información, vea Comparar XML con tipo y XML sin tipo.
Las consultas siguientes usan la expresión booleana instance of
para determinar si el atributo LocationID es de 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 consulta siguiente se especifica con la columna XML de tipo CatalogDescription. La colección de esquemas XML asociada con esta columna proporciona la información de escritura.
La consulta usa la prueba element(ElementName, ElementType?)
en la expresión instance of
para comprobar que /PD:ProductDescription[1]
devuelve un nodo de elemento con un nombre y un tipo específicos.
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 consulta devuelve True.
Ejemplo C
Al usar tipos de unión, la instance of
expresión de SQL Server tiene una limitación: En concreto, cuando el tipo de un elemento o atributo es un tipo de unión, instance of
podría no determinar el tipo exacto. Por tanto, una consulta devolverá False, a menos que los tipos atómicos utilizados en SequenceType sean los elementos principales máximos del tipo real de la expresión de la jerarquía simpleType. Es decir, los tipos atómicos especificados en SequenceType deben ser secundarios directos de anySimpleType. Para obtener información sobre la jerarquía de tipos, vea Reglas de conversión de tipos en XQuery.
En la siguiente consulta de ejemplo se realiza lo siguiente:
Se crea una colección de esquemas XML con un tipo de unión, como un tipo entero o de cadena, definido en la misma.
Declare una variable xml con tipo mediante la colección de esquemas XML.
Se asigna una instancia XML de ejemplo a la variable.
Se consulta la variable para ilustrar el comportamiento de
instance of
cuando se trata con un tipo de unión.
Esta es la consulta:
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 consulta siguiente devuelve False, pues el valor de SequenceType especificado en la expresión instance of
no es el principal máximo del tipo real de la expresión especificada. Es decir, el valor de <TestElement
> es un tipo entero. El principal máximo es xs:decimal. No obstante, no se especifica como el segundo operando del operador 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
Puesto que el principal máximo de xs:integer es xs:decimal, la consulta devolverá True si se modifica la consulta y se especifica xs:decimal como SequenceType en la misma.
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
Ejemplo D
En este ejemplo, primero se crea una colección de esquemas XML y se usa para escribir una variable xml . A continuación, se consulta la variable xml con tipo para ilustrar la instance of
funcionalidad.
La siguiente colección de esquemas XML define un tipo simple, myType y un elemento , <root
>de 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
Ahora cree una variable xml con tipo y consízela:
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
Puesto que el tipo myType procede por restricción de un tipo varchar definido en el esquema sqltypes, instance of
también devolverá 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
Ejemplo E
En el ejemplo siguiente, la expresión recupera uno de los valores del atributo IDREFS y utiliza instance of
para determinar si el valor es del tipo IDREF. En el ejemplo, se realizan las tareas siguientes:
Crea una colección de esquemas XML en la que el <
Customer
> elemento tiene un atributo de tipo OrderList IDREFS y el <Order
>elemento tiene un atributo de tipo OrderID ID.Crea una variable xml con tipo y le asigna una instancia XML de ejemplo.
Se especifica una consulta con la variable. La expresión de consulta recupera el primer valor de identificador de pedido del atributo OrderList IDREFS del primer <
Customer
>. El valor recuperado es de tipo IDREF. Por lo tanto,instance of
devuelve 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
Limitaciones de la implementación
Éstas son las limitaciones:
Los tipos de secuencia schema-element() y schema-attribute() no se admiten para la comparación con el
instance of
operador.No se admiten las secuencias completas, como
(1,2) instance of xs:integer*
.Cuando se usa una forma del tipo de secuencia element() que especifica un nombre de tipo, como
element(ElementName, TypeName)
, el tipo debe calificarse con un signo de interrogación (?). Por ejemplo,element(Title, xs:string?)
indica que el elemento puede ser NULL. SQL Server no admite la detección en tiempo de ejecución de la propiedad xsi:nil medianteinstance of
.Si el valor de
Expression
procede de un elemento o atributo escrito como unión, SQL Server solo puede identificar el tipo primitivo, no derivado, del que se deriva el tipo del valor. Por ejemplo, si <e1
> se define para tener un tipo estático de (xs:integer | xs:string), lo siguiente devolverá False.data(<e1>123</e1>) instance of xs:integer
Sin embargo,
data(<e1>123</e1>) instance of xs:decimal
devolverá True.Para los tipos de secuencia processing-instruction() y document-node(), solo se permiten formularios sin argumentos. Por ejemplo, se admite
processing-instruction()
pero noprocessing-instruction('abc')
.
Operador cast as
La conversión como expresión se puede usar para convertir un valor en un tipo de datos específico. Por ejemplo:
Expression cast as AtomicType?
En SQL Server, el signo de interrogación (?) es necesario después de AtomicType
. Por ejemplo, como se muestra en la consulta siguiente, "2" cast as xs:integer?
convierte el valor de cadena en un entero:
declare @x xml
set @x=''
select @x.query('"2" cast as xs:integer?')
En la consulta siguiente, data() devuelve el valor con tipo del atributo ProductModelID, un tipo de cadena. El cast as
operador convierte el valor en 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
El uso explícito de data() no es necesario en esta consulta. La expresión cast as
realiza una atomización implícita en la expresión de entrada.
Funciones de constructor
Se pueden utilizar las funciones de constructor de tipo atómico. Por ejemplo, en lugar de usar el cast as
operador , "2" cast as xs:integer?
puede usar la función constructor xs:integer(), como en el ejemplo siguiente:
declare @x xml
set @x=''
select @x.query('xs:integer("2")')
En el ejemplo siguiente se devuelve un valor xs:date equivalente a 2000-01-01Z.
declare @x xml
set @x=''
select @x.query('xs:date("2000-01-01Z")')
También se pueden utilizar constructores para los tipos atómicos definidos por el usuario. Por ejemplo, si la colección de esquemas XML asociada al tipo de datos XML define un tipo simple, se puede usar un constructor myType() para devolver un valor de ese tipo.
Limitaciones de la implementación
No se admiten los tipos de expresiones XQuerywitch, castable y treat .
convertir como requiere un signo de interrogación (?) después del tipo atómico.
xs:QName no se admite como un tipo para la conversión. Use expanded-QName en su lugar.
xs:date, xs:time y xs:datetime requieren una zona horaria, que se indica mediante una Z.
La consulta siguiente provocará un error, pues no se ha especificado ninguna zona horaria.
DECLARE @var XML SET @var = '' SELECT @var.query(' <a>{xs:date("2002-05-25")}</a>') go
Si se agrega el indicador de zona horaria Z al valor, la consulta funcionará.
DECLARE @var XML SET @var = '' SELECT @var.query(' <a>{xs:date("2002-05-25Z")}</a>') go
El resultado es el siguiente:
<a>2002-05-25Z</a>