Share via


Tipos de datos de XPath (SQLXML 4.0)

Se aplica a:SQL ServerAzure SQL Database

Microsoft SQL Server, XPath y XML Schema (XSD) tienen tipos de datos muy diferentes. Por ejemplo, XPath no tiene tipos de datos enteros o de fecha, pero SQL Server y XSD tienen muchos. XSD usa precisión nanosegunda para los valores de tiempo y SQL Server usa como máximo una precisión de 1/300 segundos. Por consiguiente, no siempre es posible asignar un tipo de datos a otro. Para obtener más información sobre cómo asignar SQL Server tipos de datos a tipos de datos XSD, vea Coerciones de tipos de datos y anotación sql:datatype (SQLXML 4.0).

XPath tiene tres tipos de datos: cadena, número y booleano. El tipo de datos number siempre es un punto flotante ieee 754 de precisión doble. El tipo de datos SQL Server float(53) es el más cercano al número XPath. Sin embargo, float(53) no es exactamente IEEE 754. Por ejemplo, no se utiliza NaN (no es un número) ni infinito. Si se intenta convertir una cadena no numérica en number e intentar dividir por cero, se produce un error.

Conversiones de XPath

Al utilizar una consulta de XPath como OrderDetail[@UnitPrice > "10.0"], las conversiones de tipos de datos implícitas y explícitas pueden cambiar el significado de la consulta de manera sutil. Por consiguiente, es importante entender cómo se implementan los tipos de datos de XPath. La especificación del lenguaje XPath, Lenguaje de ruta de acceso XML (XPath) versión 1.0 W3C Propuesta recomendación 8 de octubre de 1999, se puede encontrar en el sitio web de W3C en http://www.w3.org/TR/1999/PR-xpath-19991008.html.

Los operadores de XPath se dividen en cuatro categorías:

  • Operadores booleanos (and, or).

  • Operadores relacionales (<, >, <=, >=)

  • Operadores de igualdad (=, !=)

  • Operadores aritméticos (+, -, *, div, mod)

Cada categoría de operador convierte de manera diferente los operandos. Los operadores de XPath convierten implícitamente los operandos si es necesario. Los operadores aritméticos convierten sus operandos en number y dan como resultado un valor numérico. Los operadores booleanos convierten sus operandos en booleano y dan como resultado un valor booleano. Los operadores relacionales y operadores de igualdad generan un valor booleano. Sin embargo, tienen reglas de conversión distintas en función de los tipos de datos originales de sus operandos, como se muestra en esta tabla.

Operando Operador relacional Operador de igualdad
Los dos operandos son conjuntos de nodos. TRUE si y solo si hay un nodo en un conjunto y un nodo del segundo conjunto de modo que la comparación de sus valores de cadena sea TRUE. Igual.
Uno es un conjunto de nodos, el otro una cadena. TRUE si y solo si hay un nodo en el conjunto de nodos de forma que, cuando se convierte en número, la comparación de él con la cadena convertida en número es TRUE. TRUE si y solo si hay un nodo en el conjunto de nodos de forma que, cuando se convierte en cadena, la comparación de él con la cadena es TRUE.
Uno es un conjunto de nodos, el otro un número. TRUE si y solo si hay un nodo en el conjunto de nodos de forma que, cuando se convierte en número, la comparación de él con el número es TRUE. Igual.
Uno es un conjunto de nodos, el otro un booleano. TRUE si y solo si hay un nodo en el conjunto de nodos de forma que, cuando se convierte en booleano y, a continuación, en número, la comparación de él con el valor booleano convertido en número es TRUE. TRUE si y solo si hay un nodo en el conjunto de nodos de forma que, cuando se convierte en booleano, la comparación de él con el valor booleano es TRUE.
Ninguno es un conjunto de nodos. Convierta ambos operandos en number y, a continuación, compare. Convierta los dos operandos en un tipo común y, a continuación, compare. Convierta en booleano si es booleano, número si alguno de los dos es número; de lo contrario, convierta en cadena.

Nota

Dado que los operadores relacionales XPath siempre convierten sus operandos en número, no se pueden realizar comparaciones de cadenas . Para incluir comparaciones de fechas, SQL Server 2000 ofrece esta variación a la especificación XPath: cuando un operador relacional compara una cadena con una cadena, un nodo establecido en una cadena o un nodo con valores de cadena en un conjunto de nodos con valores de cadena, se realiza una comparación de cadenas (no una comparación de números).

Conversiones de conjunto de nodos

Las conversiones de conjunto de nodos no son siempre intuitivas. Un conjunto de nodos se convierte en una cadena tomando el valor de cadena solo del primer nodo del conjunto. Un conjunto de nodos se convierte en número convirtiéndolo en cadena y, a continuación, convierte la cadena en número. Un conjunto de nodos se convierte en booleano probando su existencia.

Nota

SQL Server no realiza la selección posicional en conjuntos de nodos: por ejemplo, la consulta Customer[3] XPath significa el tercer cliente; este tipo de selección posicional no se admite en SQL Server. Por lo tanto, no se implementan las conversiones node-set-to-string o node-set-to-number como se describe en la especificación XPath. SQL Server usa la semántica "any" donde la especificación XPath especifica la semántica "first". Por ejemplo, en función de la especificación XPath de W3C, la consulta Order[OrderDetail/@UnitPrice > 10.0] XPath selecciona esos pedidos con el primer OrderDetail que tiene un valor UnitPrice mayor que 10.0. En SQL Server, esta consulta XPath selecciona esos pedidos con cualquier OrderDetail que tenga un valor UnitPrice mayor que 10.0.

La conversión a booleano genera una prueba de existencia; por lo tanto, la consulta Products[@Discontinued=true()] XPath es equivalente a la expresión SQL "Products.Discontinued no es null", no a la expresión SQL "Products.Discontinued = 1". Para que la consulta sea equivalente a la última expresión SQL, primero convierta el nodo establecido en un tipo no booleano , como number. Por ejemplo, Products[number(@Discontinued) = true()].

Dado que la mayoría de los operadores están definidos para ser TRUE si son TRUE para cualquiera o uno de los nodos del conjunto de nodos, estas operaciones siempre se evalúan como FALSE si el conjunto de nodos está vacío. Así, si A está vacío, A = B y A != B son FALSE y not(A=B) y not(A!=B) son TRUE.

Normalmente, existe un atributo o elemento que se asigna a una columna si el valor de esa columna en la base de datos no es NULL. Los elementos que se asignan a filas existen si cualquiera de sus elementos secundarios existe.

Nota

Los elementos anotados con constante siempre existen. Por lo tanto, los predicados XPath no se pueden usar en elementos constantes .

Cuando un conjunto de nodos se convierte en cadena o número, su tipo XDR (si existe) se inspecciona en el esquema anotado y ese tipo se usa para determinar la conversión necesaria.

Asignar tipos de datos de XDR a tipos de datos de XPath

El tipo de datos XPath de un nodo se deriva del tipo de datos XDR en el esquema, como se muestra en la tabla siguiente (el nodo EmployeeID se usa para fines ilustrativos).

Tipo de datos XDR Tipo de datos de XPath

equivalente
Conversión de SQL Server utilizada
Nonebin.base64bin.hex N/D NingunaEmployeeID
boolean boolean CONVERT (bit, IdEmpleado)
number, int, float,i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 number CONVERT(float(53), EmployeeID)
id, idref, idrefsentity, entities, enumerationnotation, nmtoken, nmtokens, chardate, Timedate, Time.tz, string, uri, uuid string CONVERT(nvarchar(4000), EmployeeID, 126)
fixed14.4 N/D (no hay ningún tipo de datos de XPath que sea equivalente al tipo de datos fixed14.4 de XDR) CONVERT(money, EmployeeID)
date string LEFT(CONVERT(nvarchar(4000), EmployeeID, 126), 10)
time

time.tz
string SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126), 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24)

Las conversiones de fecha y hora están diseñadas para funcionar si el valor se almacena en la base de datos mediante el tipo de datos SQL Server datetime o una cadena. Tenga en cuenta que el tipo de datos SQL Server datetime no usa zona horaria y tiene una precisión menor que el tipo de datos de hora XML. Para incluir el tipo de datos de zona horaria o precisión adicional, almacene los datos en SQL Server mediante un tipo de cadena.

Cuando un nodo se convierte del tipo de datos de XDR al tipo de datos de XPath, a veces es necesaria una conversión adicional (de un tipo de datos de XPath a otro tipo de datos de XPath). Por ejemplo, considere esta consulta de XPath:

(@m + 3) = 4  

Si @m es del tipo de datos XDR fijo14.4 , la conversión del tipo de datos XDR al tipo de datos XPath se realiza mediante:

CONVERT(money, m)  

En esta conversión, el nodo m se convierte de fixed14.4 a money. Sin embargo, si se agrega el valor 3, se requiere una conversión adicional:

CONVERT(float(CONVERT(money, m))  

La expresión de XPath se evalúa como:

CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)  

Como se muestra en la tabla siguiente, ésta es la misma conversión que se aplica para otras expresiones de XPath (como expresiones de literales o compuestas).

X es desconocido X es cadena X es number X es booleano
string(X) CONVERT (nvarchar(4000), X, 126) - CONVERT (nvarchar(4000), X, 126) CASE WHEN X THEN N'true' ELSE N'false' END
number(X) CONVERT (float(53), X) CONVERT (float(53), X) - CASE WHEN X THEN 1 ELSE 0 END
boolean(X) - LEN(X) > 0 X != 0 -

Ejemplos

A. Convertir un tipo de datos en una consulta de XPath

En la siguiente consulta XPath especificada en un esquema XSD anotado, la consulta selecciona todos los nodos Employee con el valor del atributo EmployeeID de E-1, donde "E-" es el prefijo especificado mediante la anotación sql:id-prefix .

Employee[@EmployeeID="E-1"]

El predicado de la consulta es equivalente a la expresión de SQL:

N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'

Dado que EmployeeID es uno de los valores de tipo de datos id (idref, idrefs, nmtoken, nmtokens, etc.) en el esquema XSD, EmployeeID se convierte en el tipo de datos XPath de cadena mediante las reglas de conversión descritas anteriormente.

CONVERT(nvarchar(4000), Employees.EmployeeID, 126)

El prefijo "E -" se agrega a la cadena y el resultado se compara entonces con N'E-1'.

B. Realizar varias conversiones de tipos de datos en una consulta de XPath

Considere esta consulta especificada de XPath en un esquema XSD anotado: OrderDetail[@UnitPrice * @OrderQty > 98]

Esta consulta XPath devuelve todos los <elementos OrderDetail> que satisfacen el predicado @UnitPrice * @OrderQty > 98. Si UnitPrice se anota con un tipo de datos fixed14.4 en el esquema anotado, este predicado es equivalente a la expresión SQL:

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)

Para convertir los valores de la consulta de XPath, la primera conversión convierte el tipo de datos de XDR al tipo de datos de XPath. Dado que el tipo de datos XSD de UnitPrice es fixed14.4, como se describe en la tabla anterior, esta es la primera conversión que se usa:

CONVERT(money, OrderDetail.UnitPrice))   

Dado que los operadores aritméticos convierten sus operandos en el tipo de datos XPath numérico , la segunda conversión (de un tipo de datos XPath a otro tipo de datos XPath) se aplica en la que el valor se convierte en float(53) (float(53) está cerca del tipo de datos número XPath):

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))   

Suponiendo que el atributo OrderQty no tiene ningún tipo de datos XSD, OrderQty se convierte en un número de tipos de datos XPath en una sola conversión:

CONVERT(float(53), OrderDetail.OrderQty)  

Del mismo modo, el valor 98 se convierte en el tipo de datos XPath numérico:

CONVERT(float(53), 98)  

Nota

Si el tipo de datos XSD usado en el esquema no es compatible con el tipo de datos SQL Server subyacente en la base de datos, o si se realiza una conversión de tipo de datos XPath imposible, SQL Server puede devolver un error. Por ejemplo, si el atributo EmployeeID se anota con la anotación id-prefix , XPath Employee[@EmployeeID=1] genera un error, ya que EmployeeID tiene la anotación id-prefix y no se puede convertir en número.