Sistema de tipos (XQuery)
XQuery es un lenguaje con establecimiento inflexible de tipos para tipos de esquema y un lenguaje con establecimiento flexible de tipos para datos sin tipo. Los tipos predefinidos de XQuery son los siguientes:
Tipos integrados de esquema XML en el espacio de nombres http://www.w3.org/2001/XMLSchema.
Tipos definidos en el espacio de nombres http://www.w3.org/2004/07/xpath-datatypes.
En este tema también se trata lo siguiente:
El valor con tipo y el valor de cadena de un nodo.
La data (función de XQuery) y la string (función de XQuery).
La equiparación del tipo de secuencia devuelto por una expresión.
Tipos integrados de esquema XML
Los tipos integrados de esquema XML tienen el prefijo de espacio de nombres predefinido xs. Entre ellos, se encuentran xs:integer y xs:string. Todos estos tipos integrados son compatibles y se pueden utilizar al crear una colección de esquemas XML.
Al consultar XML con tipo, el tipo estático y dinámico de los nodos se determina a partir de la colección de esquemas XML asociada a la columna o variable que se consulta. Para obtener más información sobre los tipos estáticos y dinámicos, vea Contexto de expresiones y evaluación de consultas (XQuery). Por ejemplo, la consulta siguiente se especifica en una columna xml con tipo (Instructions). La expresión utiliza instance of para comprobar que el valor con tipo del atributo LotSize devuelto es de tipo xs:decimal.
SELECT Instructions.query('
DECLARE namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
data(/AWMI:root[1]/AWMI:Location[@LocationID=10][1]/@LotSize)[1] instance of xs:decimal
') AS Result
FROM Production.ProductModel
WHERE ProductModelID=7
Esta información de tipos la proporciona la colección de esquemas XML asociada a la columna.
Tipos definidos en el espacio de nombres de tipos de datos XPath
Los tipos definidos en el espacio de nombres http://www.w3.org/2004/07/xpath-datatypes tienen el prefijo predefinido xdt. La siguiente información se aplica a estos tipos:
Estos tipos no se pueden utilizar al crear una colección de esquemas XML. Estos tipos se utilizan en el sistema de tipos XQuery y se utilizan para XQuery y el establecimiento de tipos estáticos. Se puede realizar la conversión a los tipos atómicos, como xdt:untypedAtomic, en el espacio de nombres xdt.
Al consultar XML sin tipo, el tipo estático y dinámico de los nodos de elementos es xdt:untyped y el tipo de los valores de atributo es xdt:untypedAtomic. El resultado de un método query() genera XML sin tipo. Esto significa que los nodos XML se devuelven como xdt:untyped y xdt:untypedAtomic respectivamente.
No se admiten los tipos xdt:dayTimeDuration y xdt:yearMonthDuration.
En el ejemplo siguiente, la consulta se especifica con una variable XML sin tipo. La expresión, data(/a[1]), devuelve una secuencia de un valor atómico. La función data() devuelve el valor con tipo del elemento <a>. Dado que se consulta XML sin tipo, el tipo de valor devuelto es xdt:untypedAtomic. Por tanto, instance of devuelve True.
DECLARE @x xml
SET @x='<a>20</a>'
SELECT @x.query( 'data(/a[1]) instance of xdt:untypedAtomic' )
En lugar de recuperar el valor con tipo, la expresión (/a[1]) del ejemplo siguiente devuelve una secuencia de un elemento, el elemento <a>. La expresión instance of realiza la prueba de elementos para comprobar si el valor devuelto por la expresión es un nodo de elemento xdt:untyped type.
DECLARE @x xml
SET @x='<a>20</a>'
-- Is this an element node whose name is "a" and type is xdt:untyped.
SELECT @x.query( '/a[1] instance of element(a, xdt:untyped?)')
-- Is this an element node of type xdt:untyped.
SELECT @x.query( '/a[1] instance of element(*, xdt:untyped?)')
-- Is this an element node?
SELECT @x.query( '/a[1] instance of element()')
[!NOTA]
Cuando se consulta una instancia XML con tipo y la expresión de la consulta incluye el eje principal, deja de estar disponible la información del tipo estático de los nodos resultantes. Sin embargo, el tipo dinámico sigue asociado a los nodos.
Valor con tipo yvalor de cadena
Cada nodo tiene un valor con tipo y un valor de cadena. Para los datos XML con tipo, la colección de esquemas XML asociada a la columna o variable que se consulta proporciona el tipo del valor con tipo. Para los datos XML sin tipo, el tipo del valor con tipo es xdt:untypedAtomic.
Se puede utilizar la función data() o string() para recuperar el valor de un nodo:
La data (función de XQuery) devuelve el valor con tipo de un nodo.
La string (función de XQuery) devuelve el valor de cadena del nodo.
En la siguiente colección de esquemas XML, se define el elemento <root> del tipo entero:
CREATE XML SCHEMA COLLECTION SC AS N'
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="root" type="integer"/>
</schema>'
GO
En el ejemplo siguiente, la expresión primero recupera el valor con tipo de /root[1] y, después, le suma 3.
DECLARE @x xml(SC)
SET @x='<root>5</root>'
SELECT @x.query('data(/root[1]) + 3')
En el ejemplo siguiente, la expresión genera un error, porque string(/root[1]) en la expresión devuelve un valor de tipo cadena. A continuación, este valor se pasa a un operador aritmético que solo utiliza como operandos valores de tipo numérico.
-- Fails because the argument is string type (must be numeric primitive type).
DECLARE @x xml(SC)
SET @x='<root>5</root>'
SELECT @x.query('string(/root[1]) + 3')
En el ejemplo siguiente se calcula el total de los atributos LaborHours. La función data() recupera los valores con tipo de los atributos LaborHours de todos los elementos <Location> para un modelo de producto. De acuerdo con el esquema XML asociado a la columna Instruction, LaborHours es de tipo xs:decimal.
SELECT Instructions.query('
DECLARE namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
sum(data(//AWMI:Location/@LaborHours))
') AS Result
FROM Production.ProductModel
WHERE ProductModelID=7
Esta consulta devuelve 12.75 como resultado.
[!NOTA]
El uso explícito de la función data() en este ejemplo solo tiene fines ilustrativos. Si no se especifica, sum() aplica de manera implícita la función data() para extraer los valores con tipo de los nodos.