XPath のデータ型 (SQLXML 4.0)
Microsoft SQL Server 2005、XPath、および XML Schema (XSD) のデータ型は大きく異なります。たとえば、XPath に整数や日付のデータ型はありませんが、SQL Server と XSD にはこれらのデータ型が多く用意されています。また、XSD では時間値の精度はナノ秒ですが、SQL Server の精度は最大でも 1/300 秒です。このため、あるデータ型から別のデータ型へのマッピングが常に可能であるとは限りません。SQL Server のデータ型から XSD のデータ型へのマッピングに関する詳細は、「データ型の強制型変換と sql:datatype 注釈 [SQLXML 4.0]」を参照してください。
XPath には、string、number、および boolean の 3 つのデータ型があります。number 型は、常に IEEE 754 倍精度浮動小数点数です。XPath の number 型に最も近いデータ型は、SQL Server の float(53) 型です。ただし、float(53) 型は厳密には IEEE 754 ではなく、NaN (Not-a-Number) も無限大も使用されません。非数値文字列を number 型に変換し、0 での除算を試みると、エラーが発生します。
XPath 変換
OrderDetail[@UnitPrice > "10.0"]
などの XPath クエリを使用する場合は、データ型の変換を暗黙的に行うか明示的に行うかによって、クエリの意味が微妙に変わります。このため、XPath データ型の実装方法について理解しておくことが重要です。XPath 言語仕様 "XML Path Language (XPath) version 1.0 W3C Proposed Recommendation 8 October 1999" は、W3C Web サイト http://www.w3.org/TR/1999/PR-xpath-19991008.html で参照できます。
XPath の演算子は、次の 4 つのカテゴリに分けられます。
- 論理演算子 (and、or)
- 関係演算子 (<、>、<=、>=)
- 等価演算子 (=、!=)
- 算術演算子 (+、-、*、div、mod)
各カテゴリの演算子では、それぞれ異なる方法で各自のオペランドが変換されます。XPath の演算子では、必要に応じて各自のオペランドが暗黙的に変換されます。算術演算子では、オペランドが number に変換され、数値が得られます。論理演算子では、オペランドが boolean に変換され、ブール値が得られます。関係演算子と等価演算子では、ブール値が得られます。ただし、次の表に示すように、オペランドの変換元のデータ型に応じて、それぞれ異なる変換規則が使用されます。
オペランド | 関係演算子 | 等価演算子 |
---|---|---|
両方のオペランドがノード セットの場合 |
それぞれのセットにノードが 1 つあり、それらの string 値を比較した結果が TRUE の場合に限り TRUE。 |
同じ。 |
一方がノード セットで、他方が string の場合 |
ノード セットにノードが 1 つあり、それを number に変換した値と、string を number に変換した値を比較した結果が TRUE である場合に限り TRUE。 |
ノード セットにノードが 1 つあり、それを string に変換した値と、string を比較した結果が TRUE である場合に限り TRUE。 |
一方がノード セットで、他方が number の場合 |
ノード セットにノードが 1 つあり、それを number に変換した値と、number を比較した結果が TRUE である場合に限り TRUE。 |
同じ。 |
一方がノード セットで、他方が boolean の場合 |
ノード セットにノードが 1 つあり、それを boolean に変換し、その後 number に変換した値と、boolean を number に変換した値を比較した結果が TRUE である場合に限り TRUE。 |
ノード セットにノードが 1 つあり、それを boolean に変換した値と、boolean を比較した結果が TRUE である場合に限り TRUE。 |
どちらもノード セットでない場合 |
両方のオペランドを number に変換し比較。 |
両方のオペランドを共通のデータ型に変換し比較。いずれかが boolean の場合は boolean に変換し、いずれかが number の場合は number に変換します。それ以外の場合は string に変換します。 |
メモ : |
---|
XPath の関係演算子ではオペランドが常に number に変換されるので、string の比較はできません。日付の比較を含めるため、SQL Server 2000 では XPath の仕様が変更され、関係演算子で string と string、ノード セットと string、または文字列値ノード セットと文字列値ノード セットが比較される場合には、number ではなく string の比較が行われるようになりました。 |
ノード セット変換
ノード セット変換は常に直感的なものとは限りません。ノード セットから string への変換では、セット内の先頭ノードの文字列値のみが使用されます。ノード セットから number への変換では、ノード セットが一度 string に変換されてから number に変換されます。ノード セットから boolean への変換では、その存在が検査されます。
メモ : |
---|
SQL Server では、ノード セットで位置の選択は実行されません。たとえば、XPath クエリ Customer[3] は 3 番目の顧客を意味しますが、このような位置の選択は SQL Server ではサポートされていません。したがって、XPath 仕様で説明されているような、ノード セットから string、またはノード セットから number への変換は実装されていません。SQL Server では、XPath 仕様で "先頭" の意味で指定されているものが "任意" の意味として扱われます。たとえば、W3C XPath 仕様によると、Order[OrderDetail/@UnitPrice > 10.0] という XPath クエリでは、先頭の OrderDetail の UnitPrice が 10.0 を超える注文が選択されますが、SQL Server では、この XPath クエリによって、UnitPrice が 10.0 を超える任意の OrderDetail を含む注文が選択されます。 |
boolean への変換では、存在検査が生成されます。このため、Products[@Discontinued=true()]
という XPath クエリは、"Products.Discontinued = 1" という SQL 式ではなく、"Products.Discontinued is not null" という SQL 式と等価になります。"Products.Discontinued = 1" という SQL 式と等価なクエリを作成するには、最初にノード セットを number などの、boolean 以外の型に変換します。たとえば、Products[number(@Discontinued) = true()]
のようにします。
大半の演算子は、ノード セット内の 1 つ以上のノードに対して TRUE であれば TRUE となるように定義されているので、これらの演算はノード セットが空の場合は常に FALSE となります。したがって、A が空の場合、A = B
と A != B
は両方とも FALSE になり、not(A=B)
と not(A!=B)
は TRUE になります。
通常、列にマップされる属性や要素は、データベース内でその列の値が null でない場合に存在します。行にマップされる要素は、子が存在する場合に存在します。詳細については、「sql:relation の使用 (XDR スキーマ)」および「sql:field の使用 (XDR スキーマ)」を参照してください。
メモ : |
---|
is-constant で注釈される要素は常に存在します。したがって、XPath 述語を is-constant 要素に使用することはできません。詳細については、「sql:is-constant を使用した、定数要素の作成 (XDR スキーマ)」を参照してください。 |
ノード セットが string または number に変換される場合、注釈付きスキーマにその XDR 型が指定されているかどうかが調べられ、見つかった場合はその型によって必要な変換が判別されます。
XDR データ型から XPath データ型へのマッピング
次の表に示すように、ノードの XPath データ型は、スキーマ内の XDR データ型から派生します (EmployeeID は説明用のノードです)。
XDR データ型 | 同等の XPath データ型 | 使用される SQL Server 変換 |
---|---|---|
Nonebin.base64bin.hex |
N/A |
NoneEmployeeID |
boolean |
boolean |
CONVERT(bit, EmployeeID) |
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/A (XDR データ型 fixed14.4 に相当する XPath のデータ型はありません) |
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) |
日付と時刻の変換は、値が SQL Server の datetime 型と string 型のどちらを使用してデータベースに格納されている場合も、動作するよう設計されています。SQL Server の datetime 型では timezone は使用されず、XML の time 型よりも有効桁数が少ないことに注意してください。timezone 型または追加の有効桁数を含めるには、string 型を使って SQL Server にデータを格納します。
ノードが XDR データ型から XPath データ型に変換される場合は、1 つの XPath データ型から別の XPath データ型へ、追加の変換が必要になることがあります。たとえば、次の XPath クエリを考えてみます。
(@m + 3) = 4
@m が fixed14.4 XDR データ型の場合、XDR データ型から XPath データ型への変換は、次を使用して行われます。
CONVERT(money, m)
この変換で、ノード m
は fixed14.4 から money に変換されます。しかし、値 3 を加算するには追加の変換が必要になります。
CONVERT(float(CONVERT(money, m))
この XPath 式は、次のように評価されます。
CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)
次の表に示すように、これは、リテラルや複合式など、他の XPath 式に適用される変換と同じです。
|
X が不明 |
X が string |
X が number |
X が 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 |
- |
例
A. XPath クエリ内のデータ型を変換する
注釈付き XSD スキーマに対して指定されている次の XPath クエリでは、EmployeeID 属性値が E-1 であるすべての Employee ノードが選択されます。ここで "E-" は、sql:id-prefix 注釈で指定されるプレフィックスです。
Employee[@EmployeeID="E-1"]
クエリ内の述語は、次の SQL 式と等価です。
N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'
EmployeeID は、XSD スキーマの id 型 (idref、idrefs、nmtoken、nmtokens など) の値の 1 つであり、前に説明した変換規則によって string XPath データ型に変換されます。
CONVERT(nvarchar(4000), Employees.EmployeeID, 126)
文字列に "E-" プレフィックスが追加され、結果が N'E-1'
と比較されます。
B. XPath クエリ内で複数のデータ型変換を実行する
注釈付き XSD スキーマに対して指定される XPath クエリ OrderDetail[@UnitPrice * @OrderQty > 98]
を考えてみます。
この XPath クエリでは、述語 @UnitPrice * @OrderQty > 98
を満たすすべての <OrderDetail> 要素が返されます。注釈付きスキーマで、UnitPrice に fixed14.4 データ型の注釈が付けられる場合、この述語は SQL 式と同等になります。
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)
XPath クエリ内の値を変換するとき、最初の変換では、XDR データ型を XPath データ型に変換します。UnitPrice の XSD データ型は fixed14.4 なので、前の表に示すように、使用される最初の変換は次のようになります。
CONVERT(money, OrderDetail.UnitPrice))
算術演算子ではオペランドが number XPath データ型に変換されるので、1 つの XPath データ型から別の XPath データ型への追加変換が適用され、値は float(53) に変換されます。float(53) に近い XPath のデータ型は number です。
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))
OrderQty 属性に XSD データ型が指定されていない場合は、OrderQty が 1 回の変換で number XPath データ型に変換されます。
CONVERT(float(53), OrderDetail.OrderQty)
同様に、値 98 は number XPath データ型に変換されます。
CONVERT(float(53), 98)
メモ : |
---|
スキーマで使用されている XSD データ型とデータベース内の基になる SQL Server データ型に互換性がない場合、または XPath データ型変換が実行できない場合は、エラーが返されます。たとえば、EmployeeID 属性に id-prefix 注釈を付けた場合、EmployeeID には id-prefix 注釈が付けられており、number には変換できないので、XPath Employee[@EmployeeID=1] ではエラーが生成されます。 |