Share via


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 には、stringnumber、および 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 に変換した値と、stringnumber に変換した値を比較した結果が TRUE である場合に限り TRUE。

ノード セットにノードが 1 つあり、それを string に変換した値と、string を比較した結果が TRUE である場合に限り TRUE。

一方がノード セットで、他方が number の場合

ノード セットにノードが 1 つあり、それを number に変換した値と、number を比較した結果が TRUE である場合に限り TRUE。

同じ。

一方がノード セットで、他方が boolean の場合

ノード セットにノードが 1 つあり、それを boolean に変換し、その後 number に変換した値と、booleannumber に変換した値を比較した結果が TRUE である場合に限り TRUE。

ノード セットにノードが 1 つあり、それを boolean に変換した値と、boolean を比較した結果が TRUE である場合に限り TRUE。

どちらもノード セットでない場合

両方のオペランドを number に変換し比較。

両方のオペランドを共通のデータ型に変換し比較。いずれかが boolean の場合は boolean に変換し、いずれかが number の場合は number に変換します。それ以外の場合は string に変換します。

ms172002.note(ja-jp,SQL.90).gifメモ :
XPath の関係演算子ではオペランドが常に number に変換されるので、string の比較はできません。日付の比較を含めるため、SQL Server 2000 では XPath の仕様が変更され、関係演算子で stringstring、ノード セットと string、または文字列値ノード セットと文字列値ノード セットが比較される場合には、number ではなく string の比較が行われるようになりました。

ノード セット変換

ノード セット変換は常に直感的なものとは限りません。ノード セットから string への変換では、セット内の先頭ノードの文字列値のみが使用されます。ノード セットから number への変換では、ノード セットが一度 string に変換されてから number に変換されます。ノード セットから boolean への変換では、その存在が検査されます。

ms172002.note(ja-jp,SQL.90).gifメモ :
SQL Server では、ノード セットで位置の選択は実行されません。たとえば、XPath クエリ Customer[3] は 3 番目の顧客を意味しますが、このような位置の選択は SQL Server ではサポートされていません。したがって、XPath 仕様で説明されているような、ノード セットから string、またはノード セットから number への変換は実装されていません。SQL Server では、XPath 仕様で "先頭" の意味で指定されているものが "任意" の意味として扱われます。たとえば、W3C XPath 仕様によると、Order[OrderDetail/@UnitPrice > 10.0] という XPath クエリでは、先頭の OrderDetailUnitPrice が 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 = BA != B は両方とも FALSE になり、not(A=B)not(A!=B) は TRUE になります。

通常、列にマップされる属性や要素は、データベース内でその列の値が null でない場合に存在します。行にマップされる要素は、子が存在する場合に存在します。詳細については、「sql:relation の使用 (XDR スキーマ)」および「sql:field の使用 (XDR スキーマ)」を参照してください。

ms172002.note(ja-jp,SQL.90).gifメモ :
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

@mfixed14.4 XDR データ型の場合、XDR データ型から XPath データ型への変換は、次を使用して行われます。

CONVERT(money, m)

この変換で、ノード mfixed14.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 型 (idrefidrefsnmtokennmtokens など) の値の 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> 要素が返されます。注釈付きスキーマで、UnitPricefixed14.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)
ms172002.note(ja-jp,SQL.90).gifメモ :
スキーマで使用されている XSD データ型とデータベース内の基になる SQL Server データ型に互換性がない場合、または XPath データ型変換が実行できない場合は、エラーが返されます。たとえば、EmployeeID 属性に id-prefix 注釈を付けた場合、EmployeeID には id-prefix 注釈が付けられており、number には変換できないので、XPath Employee[@EmployeeID=1] ではエラーが生成されます。