XQuery と静的な型指定

適用対象:SQL Server

SQL Serverの XQuery は、静的に型指定された言語です。 つまり、式が特定の関数または演算子で受け入れられない型またはカーディナリティを持つ値を返すと、クエリのコンパイル中に型エラーが発生します。 さらに、静的型チェックでは、型指定された XML ドキュメントのパス式が誤って入力されているかどうかを検出することもできます。 XQuery コンパイラは、アトミック化などの暗黙的な操作を加える正規化を適用してから、静的な型の推定および確認を行います。

静的な型の推定

静的な型の推定では、式の戻り型が判定されます。 この判定は、入力パラメーターの静的な型および演算の静的なセマンティクスを取得し、結果の静的な型を推定することで行われます。 たとえば、式 1 + 2.3 の静的型は次のように決定されます。

  • 静的型 1 は xs:integer で、2.3 の静的型は xs:decimal です。 動的セマンティクスに基づいて、演算の + 静的セマンティクスによって整数が 10 進数に変換され、10 進数が返されます。 推定される静的型は xs:decimal になります

型指定されていない XML インスタンスの場合、データが型指定されていないことを示す特殊な型があります。 その情報は、静的な型チェックのときに暗黙的に型をキャストするために使用されます。

型指定されたデータの場合、XML データ型インスタンスを制約する XML スキーマ コレクションから入力の型が推定されます。 たとえば、スキーマで xs:integer 型の要素のみが許可されている場合、その要素を使用したパス式の結果は 、xs:integer 型の 0 個以上の要素になります。 これは現在、アスタリスク (*) が結果の型のカーディナリティを示すなどの element(age,xs:integer)* 式を使用して表されています。 この例では、式の名前が "age" で xs:integer 型の要素が 0 個以上になる場合があります。 その他のカーディナリティは 1 つだけであり、型名のみを使用して表され、0 または 1 を使用し、疑問符 (?) を使用して表現され、1 つ以上がプラス記号 (+) を使用して表現されます。

静的型の推論では、式が常に空のシーケンスを返す可能性があります。 たとえば、型指定された XML データ型のパス式で、customer> 要素 (/customer/name) 内<で name> 要素を検索<しても、スキーマで顧客>内<の名前>が許可<されていない場合、静的型推論では結果が空であると推論されます。 これは、正しくないクエリを検出するために使用され、式が () または data( () でない限り、静的エラーとして報告されます。

詳細な推論規則は、XQuery 仕様の正式なセマンティクスで提供されています。 マイクロソフトでは、型指定された XML データ型のインスタンスに対応するためにこの規則を少しだけ変更しました。 標準からの最も重要な変更点は、暗黙的なドキュメント ノードで XML データ型のインスタンスの型を認識することです。 その結果、/age という形式のパス式は、その情報に基づいて正確に型指定されます。

SQL Server Profilerテンプレートと権限を使用すると、クエリ コンパイルの一部として返される静的型を確認できます。 これらを確認するには、トレースに TSQL イベント カテゴリの XQuery Static Type イベントが含まれている必要があります。

静的な型チェック

静的な型チェックにより、実行時の実行で、操作に適した型の値のみを受け取ります。 実行時には必ずしも型がチェックされるとは限りませんが、コンパイルの初期段階で潜在的なエラーを検出できます。 これにより、パフォーマンスが向上します。 ただし、静的な型指定を使用する場合、クエリの記述には通常以上の配慮が必要になります。

次に、使用できる適切な型を示します。

  • 関数または操作によって明示的に許可される型。

  • 明示的に許可されている型のサブタイプ。

サブタイプは、XML スキーマの制約または拡張による派生を使用するためのサブタイプ指定規則に基づいて定義されます。 たとえば、型が S であるすべての値が型 T のインスタンスでもある場合、型 S は型 T のサブタイプです。

さらに、すべての整数値は、XML スキーマの種類階層に基づく 10 進数の値でもあります。 一方、decimal 型のすべての値が integer 型の値であるとは限りません。 したがって、整数は decimal のサブタイプですが、その逆ではありません。 たとえば、操作では+、数値型 xs:integer、xs:decimal、xs:floatxs:double など、特定の型値のみを使用できます。 xs:string などの他の型の値を渡すと、型エラーが発生します。 これは、厳密な型指定と呼ばれます。 型指定されていない XML を示すために使用されるアトミック型など、他の型の値は、操作が受け入れる型の値に暗黙的に変換できます。 これは弱い型指定と呼ばれます。

暗黙的な変換の後での静的な型チェックを必須にした場合、カーディナリティが正しく、許可された型の値のみが演算に渡されます。 "string" + 1 の場合、"string" の静的型が xs:string であると認識されます。 これは操作で許可される型 + ではないので、型エラーが発生します。

任意の式 E1 の結果に任意の式 E2 を加算する (E1 + E2) 場合、静的な型の推定によって E1 および E2 の静的な型が判定されたうえで、それらの型が演算に許可されている型であるかどうかのチェックが行われます。 たとえば、E1 の静的型に xs:string または xs:integer を指定できる場合、実行時に一部の値が整数である場合でも、静的型チェックでは型エラーが発生します。 E1 の静的型が xs:integer* の場合も同様です。 操作は + 1 つの整数値のみを受け取り、E1 は 0 または 1 を超える値を返すことができるため、静的型チェックではエラーが発生します。

前述のように、型の推論では、渡されるデータの型についてユーザーが知っているよりも広い型が推論されることが多いです。 そのような場合は、ユーザーがクエリを書き換える必要があります。 一般的なケースには、次のようなものがあります。

  • スーパータイプまたは型の共用体など、汎化された型が推定される。 型がアトミック型の場合は、キャスト式またはコンストラクター関数を使用して、実際の静的型を示す必要があります。 たとえば、式 E1 の推論された型が xs:string または xs:integer のどちらかの選択肢であり、加算に xs:integer が必要な場合は、 ではなく E1+E2を記述xs:integer(E1) + E2する必要があります。 xs:integer にキャストできない文字列値が検出された場合、この式は実行時に失敗する可能性があります。 ただし、この式は静的な型チェックには合格します。 この式は空のシーケンスにマップされます。

  • データの実際の内容を上回るカーディナリティが推定される。 これは、xml データ型に複数の最上位要素を含めることができるため、XML スキーマ コレクションでこれを制限できないため、頻繁に発生します。 静的な型を限定し、渡される値の数を 1 以下にするためには、位置関係の述語 [1] を使用してください。 たとえば、 要素bの最上位レベルの要素の属性cの値に 1 を追加するには、 を指定する必要がありますwrite (/a/b/@c)[1]+1。 さらに、DOCUMENT キーワードは XML スキーマ コレクションと共に使用できます。

  • 一部の操作では、推論中に型情報が失われます。 たとえば、ノードの種類を特定できない場合は、 anyType になります。 これは暗黙的に他の型にキャストされません。 これらの変換は、親軸を使用してナビゲーション中に最も顕著に発生します。 式で静的な型のエラーが発生する場合、そのような演算の使用は避け、クエリを書き換えてください。

共用体型の型チェック

共用体型では、型チェックのために慎重な処理が必要です。 次の例では、2 つの問題を示します。

例: 共用体の型に対する関数

共用体型の <r> 要素定義を考えてみましょう。

<xs:element name="r">  
<xs:simpleType>  
   <xs:union memberTypes="xs:int xs:float xs:double"/>  
</xs:simpleType>  
</xs:element>  

XQuery コンテキスト内では、xQuery コンパイラは fn:avg() の引数の要素に異なる型 (xs:intxs:floatまたは xs:double) <r> の値を追加できないため、"average" 関数fn:avg (//r)は静的エラーを返します。 これを解決するには、関数呼び出しを として fn:avg(for $r in //r return $r cast as xs:double ?)書き直します。

例: 和集合型の演算子

加算演算 ('+') には、オペランドの正確な型が必要です。 その結果、式 (//r)[1] + 1 は、要素 の前に説明した型定義を持つ静的エラーを <r>返します。 解決策の 1 つは、「(//r)[1] cast as xs:int? +1」("?" は 0 回または 1 回の出現を示す) に書き換える方法です。 実行時エラーの結果として、キャストによって空のシーケンスが発生する可能性があるため、SQL Serverには "?"" を使用して "キャスト as" が必要です。

参照

XQuery 言語リファレンス (SQL Server)