Types de données XPath (SQLXML 4.0)
S’applique à : SQL ServerAzure SQL Database
Microsoft SQL Server, XPath et XML Schema (XSD) ont des types de données très différents. Par exemple, XPath n’a pas de types de données entiers ou de date, mais SQL Server et XSD ont beaucoup. XSD utilise la précision nanoseconde pour les valeurs temporelles, et SQL Server utilise au maximum une précision de 1/300 secondes. 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 des types de données SQL Server aux types de données XSD, consultez Contraintes de type de données et annotation sql :datatype (SQLXML 4.0).
XPath a trois types de données : chaîne, nombre et booléen. Le type de données number est toujours un virgule flottante à double précision IEEE 754. Le type de données float(53) SQL Serverest le plus proche du nombre XPath. Toutefois, float(53) n’est pas exactement IEEE 754. Par exemple, ni la valeur NaN (Not-a-Number,), ni une valeur infinie n'est employée. La tentative de conversion d’une chaîne non numérique en nombre et la tentative 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, XPath Path Language (XPath) version 1.0 W3C Proposée recommandation 8 octobre 1999, se trouve 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 nombre et entraînent une valeur numérique. Les opérateurs booléens convertissent leurs opérandes en booléen et entraînent 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 seulement s’il existe un nœud dans un seul jeu et un nœud dans le deuxième jeu de sorte que la comparaison de leurs valeurs de chaîne soit TRUE. | Identique. |
L’un est un jeu de nœuds, l’autre une chaîne. | TRUE si et uniquement s’il existe un nœud dans le jeu de nœuds de sorte qu’en cas de conversion en nombre, la comparaison avec la chaîne convertie en nombre est TRUE. | TRUE si et uniquement s’il existe un nœud dans le jeu de nœuds de sorte qu’en cas de conversion en chaîne, la comparaison de celle-ci avec la chaîne est TRUE. |
L’un est un ensemble de nœuds, l’autre un nombre. | TRUE si et uniquement s’il existe un nœud dans le jeu de nœuds de sorte qu’en cas de conversion en nombre, la comparaison avec le nombre est TRUE. | Identique. |
L’un est un jeu de nœuds, l’autre un booléen. | TRUE si et seulement s’il existe un nœud dans le jeu de nœuds de sorte qu’en cas de conversion en booléen , puis en nombre, la comparaison avec la valeur booléenne convertie en nombre est TRUE. | TRUE si et uniquement s’il existe un nœud dans le jeu de nœuds de sorte qu’en cas de conversion en booléen, la comparaison avec la valeur booléenne est TRUE. |
Ni l'un ni l'autre n'est un élément node-set. | Convertissez les deux opérandes en nombre , puis comparez. | Convertissez les deux opérandes en un type commun, puis comparez-les. Convertissez en booléen si l’un ou l’autre est booléen, nombre s’il s’agit d’un nombre ; sinon, convertissez en chaîne. |
Remarque
Étant donné que les opérateurs relationnels XPath convertissent toujours leurs opérandes en nombre, les comparaisons de chaînes ne sont pas possibles. Pour inclure des comparaisons de dates, SQL Server 2000 offre cette variante à la spécification XPath : lorsqu’un opérateur relationnel compare une chaîne à une chaîne, un nœud défini sur une chaîne ou un nœud à valeur chaîne défini sur un jeu de nœuds à valeur chaîne, une comparaison de chaînes (et non une comparaison de nombres) est effectuée.
Conversions des éléments node-set
Les conversions des éléments node-set ne sont pas toujours intuitives. Un jeu de nœuds est converti en chaîne en prenant la valeur de chaîne du premier nœud du jeu. Un jeu de nœuds est converti en nombre en le convertissant en chaîne, puis en la convertissant en nombre. Un jeu de nœuds est converti en booléen en testant son existence.
Remarque
SQL Server n’effectue pas de sélection positionnelle sur des jeux de nœuds : par exemple, la requête Customer[3]
XPath signifie le troisième client ; ce type de sélection positionnelle n’est pas pris en charge dans SQL Server. Par conséquent, les conversions node-set-to-string ou node-set-to-number, comme décrit par la spécification XPath ne sont pas implémentées. SQL Server utilise la sémantique « any » où que 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 ces 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 qui a un UnitPrice supérieur à 10.0.
La conversion en booléen génère un test d’existence ; par conséquent, la requête Products[@Discontinued=true()]
XPath équivaut à l’expression SQL « Products.Discontinued n’est pas null », et non à l’expression SQL « Products.Discontinued = 1 ». Pour rendre la requête équivalente à cette dernière expression SQL, commencez par convertir le nœud défini en un type non booléen , tel que le nombre. 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.
Remarque
Les éléments annotés avec une constante is existent toujours. Par conséquent, les prédicats XPath ne peuvent pas être utilisés sur des éléments is-constant .
Lorsqu’un jeu de nœuds est converti en chaîne ou en nombre, son type XDR (le cas échéant) est inspecté dans le schéma annoté et ce type est 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 node 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 | S/O | NoneEmployeeID |
booléen | booléen | 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 si la valeur est stockée dans la base de données à l’aide du type de données datetime SQL Serverou d’une chaîne. Notez que le type de données datetime SQL Servern’utilise pas le fuseau horaire et a une précision inférieure au type de données de temps XML. Pour inclure le type de données de fuseau horaire ou une précision supplémentaire, stockez les données dans SQL Server à l’aide d’un type de chaîne .
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
S’il @m s’agit du type de données XDR fixe14.4 , la conversion du type de données XDR en type de données XPath est effectuée à l’aide de :
CONVERT(money, m)
Dans cette conversion, le nœud m
est converti de fixe14.4 en argent. 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 chaîne | X est nombre | X est booléen | |
---|---|---|---|---|
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 à un schéma XSD annoté, la requête sélectionne tous les nœuds Employee avec la valeur d’attribut EmployeeID de 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 des valeurs de type de données ID (idref, idrefs, nmtoken, nmtokens, et ainsi de suite) dans le schéma XSD, EmployeeID est converti en type de données XPath de chaîne à l’aide 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> répondant au prédicat @UnitPrice * @OrderQty > 98
. Si UnitPrice est annoté avec un type de données fixe14.4 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 de UnitPrice est fixe14.4, comme décrit dans le tableau précédent, il s’agit de la première conversion utilisée :
CONVERT(money, OrderDetail.UnitPrice))
Étant donné que les opérateurs arithmétiques convertissent leurs opérandes en type de données XPath nombre, la deuxième conversion (d’un type de données XPath vers un autre type de données XPath) est appliquée dans laquelle la valeur est convertie en float(53) (float(53) est proche du type de données de nombre XPath) :
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 de données XPath numérique dans une seule conversion :
CONVERT(float(53), OrderDetail.OrderQty)
De même, la valeur 98 est convertie en type de données XPath nombre :
CONVERT(float(53), 98)
Remarque
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 l’annotation de préfixe d’ID, le XPath Employee[@EmployeeID=1]
génère une erreur, car EmployeeID a l’annotation de préfixe d’ID et ne peut pas être converti en nombre.