Partager via


Types de données XPath (SQLXML 4.0)

Microsoft SQL Server, XPath et schéma XML (XSD) ont des types de données très différents. Par exemple, XPath n’a pas de types de données entiers ou date, mais SQL Server et XSD en ont plusieurs. XSD utilise une précision nanoseconde pour les valeurs de temps, et SQL Server utilise une précision de 1/300 seconde maximum. Par conséquent, le mappage d'un type de données à un autre n'est pas toujours possible. Pour plus d’informations sur le mappage SQL Server types de données aux types de données XSD, consultez Contraintes de type de données et l’annotation sql:datatype (SQLXML 4.0).

XPath possède trois types de données : string, number et boolean. Le type de données number est toujours une valeur à virgule flottante double précision IEEE 754. Le type de données SQL Serverfloat(53) est le plus proche de XPath number. Toutefois, le type float(53) n'est pas exactement une valeur IEEE 754. Par exemple, ni la valeur NaN (Not-a-Number,), ni une valeur infinie n'est employée. Toute tentative de conversion d'une chaîne non numérique en type number et de division par zéro entraîne une erreur.

Conversions XPath

Lorsque vous utilisez une requête XPath, telle que OrderDetail[@UnitPrice > "10.0"], les conversions de type de données implicites et explicites peuvent modifier la signification de la requête de manière subtile. Par conséquent, il est primordial de comprendre la manière dont les types de données Xpath sont implémentés. La spécification du langage XPath, XML Path Language (XPath) version 1.0 W3C Proposed Recommandation 8 octobre 1999, est disponible sur le site Web W3C à l’adresse http://www.w3.org/TR/1999/PR-xpath-19991008.html.

Les opérateurs XPath sont divisés en quatre catégories :

  • Opérateurs booléens (et, ou)

  • Opérateurs relationnels (<, , <>=, >=)

  • Opérateurs d'égalité (=, !=)

  • Opérateurs arithmétiques (+, -, *, div, mod)

Chaque catégorie d'opérateur convertit ses opérandes de manière distincte. Les opérateurs XPath convertissent implicitement leurs opérandes si cela est nécessaire. Les opérateurs arithmétiques convertissent leurs opérandes en type number et génèrent une valeur numérique. Les opérateurs booléens convertissent leurs opérandes en boolean et génèrent une valeur booléenne. Les opérateurs relationnels et d'égalité génèrent une valeur booléenne. Toutefois, ils suivent des règles de conversion différentes en fonction des types de données d'origine de leurs opérandes comme le montre le tableau ci-après.

Opérande Opérateur relationnel Opérateur d’égalité
Les deux opérandes sont des éléments node-set. TRUE si et uniquement s'il existe un nœud dans un jeu et un nœud dans le deuxième jeu justifiant que la comparaison de leurs valeurs string soit TRUE. Idem.
L'un est un élément node-set, l'autre est de type string. TRUE si et uniquement s'il existe un nœud dans l'élément node-set de sorte que, en cas de conversion en type number, sa comparaison avec la valeur string convertie en number est TRUE. TRUE si et uniquement s'il existe un nœud dans l'élément node-set de sorte que, en cas de conversion en type string, sa comparaison avec la valeur string est TRUE.
L'un est un élément node-set, l'autre est de type number. TRUE si et uniquement s'il existe un nœud dans l'élément node-set de sorte que, en cas de conversion en type number, sa comparaison avec la valeur number est TRUE. Idem.
L'un est un élément node-set, l'autre est de type boolean. TRUE si et uniquement s'il existe un nœud dans l'élément node-set de sorte que, en cas de conversion en type boolean, puis en type number, sa comparaison avec la valeur boolean convertie en number est TRUE. TRUE si et uniquement s'il existe un nœud dans l'élément node-set de sorte que, en cas de conversion en type boolean, sa comparaison avec la valeur boolean est TRUE.
Ni l'un ni l'autre n'est un élément node-set. Convertissez les deux opérandes en type number, puis comparez-les. Convertissez les deux opérandes en un type commun, puis comparez-les. Convertissez en type boolean si l'une des valeurs est de type boolean, en number si l'une des valeurs est de type number ; sinon, effectuez une conversion en type string.

Notes

Parce que les opérateurs relationnels XPath convertissent toujours leurs opérandes en number, les comparaisons de valeurs string ne sont pas possibles. Pour inclure des comparaisons de date, SQL Server 2000 propose la variante suivante par rapport à la recommandation XPath : lorsqu'un opérateur relationnel compare une valeur string à une autre valeur string, un élément node-set à une valeur string, ou deux éléments node-set à valeur de chaîne entre eux, une comparaison de la valeur string (et non une comparaison de number) a lieu.

Conversions des éléments node-set

Les conversions des éléments node-set ne sont pas toujours intuitives. Un élément node-set est converti en type string par extraction de la valeur de chaîne du premier nœud du jeu uniquement. Pour être converti en type number, un élément node-set est d'abord converti en type string, puis le type string est converti en type number. Pour convertir un élément node-set en type boolean, vous devez d'abord le tester pour vérifier s'il existe.

Notes

SQL Server n’effectue pas de sélection positionnelle sur les jeux de nœuds : par exemple, la requête Customer[3] XPath désigne le troisième client ; ce type de sélection positionnelle n’est pas pris en charge dans SQL Server. Par conséquent, les conversions d'élément node-set en string ou d'élément node-set en number, telles que décrites dans la recommandation XPath, ne sont pas implémentées. SQL Server utilise la sémantique « any » partout où la spécification XPath spécifie la sémantique « first ». Par exemple, en fonction de la spécification XPath W3C, la requête Order[OrderDetail/@UnitPrice > 10.0] XPath sélectionne les commandes avec le premier OrderDetail qui a un UnitPrice supérieur à 10.0. Dans SQL Server, cette requête XPath sélectionne ces commandes avec n’importe quel OrderDetail dont la valeur UnitPrice est supérieure à 10.0.

La conversion en valeur boolean implique un test de vérification d'existence ; la requête XPath Products[@Discontinued=true()] équivaut donc à l'expression SQL « Products.Discontinued is not null » et non à l'expression SQL « Products.Discontinued = 1 ». Pour que la requête équivaille à la dernière expression SQL, convertissez avant tout l'élément node-set en type non boolean, tel que number. Par exemple : Products[number(@Discontinued) = true()].

Du fait que la plupart des opérateurs sont définis pour être vrais (TRUE) s'ils le sont pour un nœud quelconque ou l'un des nœuds de l'élément node-set, ces opérations prennent toujours la valeur FALSE si l'élément node-set est vide. Ainsi donc, si A est vide, A = B et A != B ont tous les deux la valeur FALSE et not(A=B) et not(A!=B) ont la valeur TRUE.

En règle générale, un attribut ou un élément mappé à une colonne existe si la valeur de cette colonne dans la base de données n'est pas null. Les éléments mappés aux lignes existent si tous leurs enfants existent.

Notes

Les éléments annotés avec is-constant existent toujours. Par conséquent, les prédicats XPath ne peuvent être utilisés dans des éléments is-constant.

Lorsque vous convertissez un élément node-set en type string ou number, son type XDR (le cas échéant) est examiné dans le schéma annoté et utilisé pour déterminer la conversion requise.

Mappage des types de données XDR et XPath

Le type de données XPath d’un nœud est dérivé du type de données XDR dans le schéma, comme indiqué dans le tableau suivant (le nœud EmployeeID est utilisé à des fins d’illustration).

Type de données XDR Équivalent

Type de données XPath
Conversion SQL Server utilisée
Nonebin.base64bin.hex N/A NoneEmployeeID
boolean boolean CONVERT(bit, EmployeeID)
number, int, float,i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 nombre 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/A (aucun type de données XPath n'équivaut au type de données XDR fixed14.4) 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)

Les conversions de date et d’heure sont conçues pour fonctionner que la valeur soit stockée dans la base de données à l’aide du type de données SQL Serverdatetime ou d’un string. Notez que le type de données SQL Serverdatetime n’utilise timezone pas et a une précision inférieure à celle du type de données XMLtime. Pour inclure le type de timezone données ou une précision supplémentaire, stockez les données dans SQL Server à l’aide d’un string type.

Lorsque vous convertissez un nœud du type de données XDR en type de données XPath, une conversion supplémentaire est parfois nécessaire (d'un type de données XPath vers un autre type de données XPath). Par exemple, imaginez la requête XPath suivante :

(@m + 3) = 4  

Si @m est du fixed14.4 type de données XDR, la conversion du type de données XDR en type de données XPath s’effectue à l’aide de :

CONVERT(money, m)  

Dans le cadre de cette conversion, le nœud m passe du type fixed14.4 au type money. Toutefois, l'ajout de la valeur 3 nécessite une autre conversion :

CONVERT(float(CONVERT(money, m))  

L'expression XPath est évaluée comme suit :

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

Comme le montre le tableau ci-dessous, il s'agit de la même conversion que celle appliquée à d'autres expressions XPath (telles que des littéraux ou des expressions composées).

X est inconnu X est de type string X est de type number X est de type boolean
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 -

Exemples

R. Convertir un type de données dans une requête XPath

Dans la requête XPath suivante spécifiée par rapport au schéma XSD annoté, la requête sélectionne tous les nœuds Employee avec la valeur d’attribut EmployeeID E-1, où « E- » est le préfixe spécifié à l’aide de l’annotation sql:id-prefix .

Employee[@EmployeeID="E-1"]

Le prédicat dans la requête équivaut à l'expression SQL suivante :

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

Étant donné que EmployeeID est l’une id des valeurs de type de données (idref, idrefs, nmtoken, nmtokenset ainsi de suite) dans le schéma XSD, EmployeeID est converti en type de données XPath à l’aide string des règles de conversion décrites précédemment.

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

Le préfixe « E - » est ajouté à la chaîne et le résultat est ensuite comparé avec N'E-1'.

B. Effectuer plusieurs conversions de types de données dans une requête XPath.

Examinez la requête XPath suivante définie par rapport à un schéma XSD annoté : OrderDetail[@UnitPrice * @OrderQty > 98]

Cette requête XPath retourne tous les <éléments OrderDetail> satisfaisant le prédicat @UnitPrice * @OrderQty > 98. Si unitPrice est annoté avec un fixed14.4 type de données dans le schéma annoté, ce prédicat est équivalent à l’expression SQL :

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

Lors de la conversion des valeurs dans la requête XPath, la première conversion convertit le type de données XDR en type de données XPath. Étant donné que le type de données XSD d’UnitPrice est fixed14.4, comme décrit dans le tableau précédent, il s’agit de la première conversion utilisée :

CONVERT(money, OrderDetail.UnitPrice))   

Du fait que les opérateurs arithmétiques convertissent leurs opérandes en type de données XPath number, la deuxième conversion (d'un type de données XPath à un autre) est appliquée là où la valeur est convertie en float(53) (float(53) est très proche du type de données XPath number) :

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

En supposant que l’attribut OrderQty n’a pas de type de données XSD, OrderQty est converti en type number de données XPath en une seule conversion :

CONVERT(float(53), OrderDetail.OrderQty)  

La valeur 98 est également convertie en type de données XPath number :

CONVERT(float(53), 98)  

Notes

Si le type de données XSD utilisé dans le schéma est incompatible avec le type de données SQL Server sous-jacent dans la base de données, ou si une conversion de type de données XPath impossible est effectuée, SQL Server peut retourner une erreur. Par exemple, si l’attribut EmployeeID est annoté avec id-prefix une annotation, le XPath Employee[@EmployeeID=1] génère une erreur, car EmployeeID a l’annotation id-prefix et ne peut pas être converti numberen .