執筆者 : Shankar Pal
Microsoft Corporation
October 2003
日本語版最終更新日 2003 年 12 月 9 日
対象 :
Microsoft® SQL Server™
概要 : SQL Server "Yukon" の XML データ モデリングと使用法のガイドラインについて、具体例を提示しながら習得します。 本書の最も重要な点を理解するには、SQL Server との関連で XML 機能に精通している必要があります。
目次
はじめに
データ モデリング
使用法
異領域へのクエリ
XML スキーマへのクエリ
はじめに
Microsoft® SQL Server™ "Yukon" では、XML データ処理が幅広くサポートされます。 XML 値はネイティブに XML データ型の列に保存されます。この列には XML スキーマ名前空間に従って型を設定しても、また型の設定を省略してもかまいません。 XML 列にはインデックスを設定できます。 さらに、XQuery、および XQuery をデータ変更用に拡張した XML DML により、きめ細かいデータ操作が実現されます。
SQL Server 2000 および SQLXML Web Release では、強力な XML データ管理機能が提供されています。 この管理機能の主眼は、リレーショナル データと XML データのマッピングです。したがって、注釈付き XSD (Annotated XSD; AXSD) を使用してリレーショナル データの XML ビューを定義できる、XML 主体のアプローチが実現されます。 このようなビューでは、一括読み込み、クエリ、および更新の機能がサポートされます。 また、(FOR XML により) リレーショナル クエリの結果を XML にマッピングしたり、(OpenXML により) XML を使用したリレーショナル ビューを生成するための Transact-SQL 拡張機能が提供されています。 SQL Server "Yukon" でも、これらの機能が引き続き拡張されています。 SQL Server "Yukon" のネイティブな XML サポートと併用する、半構造化された状態のデータや、構造化されていないデータを管理する強力なアプリケーションを開発できます。
本書では、SQL Server "Yukon" の XML データ モデリングと使用法のガイドラインを示します。 本書は、次の 2 つのトピックから構成されています。
-
データ モデリング
SQL Server "Yukon" では、XML データ型、テーブルの XML ビューなどを使用して、XML データを複数の方法で保存できます。 このトピックでは、XML データ モデリングの際に適切な方法を選択するためのガイドラインを示します。 また、XML データへのインデックス設定、プロパティの昇格、および XML インスタンスの型指定についても扱います。
-
使用法
関連の深い機能、およびそのような機能の適切な使用法について、このトピックで説明します。 例を示して概念をわかりやすくしています。
データ モデリング
ここでは、SQL Server "Yukon" で XML を使用する理由、ネイティブの XML ストレージと XML ビュー テクノロジのどちらを選択するか、XML データへのインデックス設定、およびプロパティの昇格についての概要を説明します。
データを汎用的に使用できるようプラットフォームに依存しないモデルを必要とする場合、および以下の特性を満たしている場合、XML を選択するのが適しています。
以上の条件をいずれも満たさない場合、リレーショナル モデリングの使用を推奨します。
SQL Server "Yukon" で XML を保存する理由
SQL Server "Yukon" で XML 機能を使用するのには、いくつかの理由があります。
-
XML データの共有、クエリ、および変更を効率的かつトランザクションとして行うため。 アプリケーションにとって、きめ細かいデータ アクセスは重要です。 たとえば、ドキュメントの一部を抽出したり、ドキュメント全体を上書きすることなく新しいセクションを追加できます。
-
XML スキーマを基づくデータをサーバーで検証するため。
-
優れたクエリ オプティマイザを使用して XML クエリを最適化するため。
-
リレーショナル データと SQL アプリケーションがあり、アプリケーションにリレーショナル データと XML データの相互運用性が必要とされるため。 異領域へのデータ操作を実行するにはクエリとデータを変更するための言語サポートが必要です。
-
XML データを管理するデータベース サーバーの管理機能 (たとえば、バックアップと復元) を使用するため。
-
SOAP、ADO.NET、OLE DB により XML データにアクセスするため。
以上の条件をいずれも満たさない場合、データを [n]varchar(max)、varbinary(max) など、XML ではない large object 型として保存することを推奨します。
XML テクノロジを選択する
SQL Server "Yukon" では、XML をネイティブに保存するか、リレーショナル データを XML ビューで表現できます。 どちらの XML テクノロジを選択するかは、主に次の要因により決定します。
-
保存オプション :
XML データには、大きなオブジェクトの保存に適しているもの (製品マニュアルなど) と、リレーショナル列への保存に向いているもの (XML に変換したテーブル状のデータなど) があります。 いずれの保存オプションも、程度は異なりますがドキュメントの再現性は保たれます。
-
クエリ機能 :
保存オプションによる程度の差はありますが、XML ノードの述語評価など、XML データのきめ細かいクエリがサポートされます。 クエリの性質と、XML データをクエリする程度に基づいて、最適な保存オプションを選択してください。
-
XML データへのインデックス設定 :
XML クエリのパフォーマンスを重要視する場合、XML データにインデックスを設定できます。 インデックス設定のオプションは保存オプションによって異なります。アプリケーションを最適に稼動するには、適切なオプションを選択する必要があります。
-
データ変更機能 :
ワークロードには XML データのきめ細かい変更を必要とするもの (たとえば、ドキュメントに新しいセクションを追加するなど) と、そのような必要のないもの (Web コンテンツ管理など) があります。 適切なデータ変更言語のサポートがアプリケーションにとって重要になる場合があります。
-
スキーマのサポート :
XML データにスキーマが適用されている場合があります。 スキーマは、XSD で記述できます。 これらがサポートされるかどうかは、XML テクノロジによって異なります。
言うまでもなく、選択肢を変更すれば、それに応じてパフォーマンス特性も変わります。
保存オプション
SQL Server "Yukon" における XML の保存オプションは次のとおりです。
-
XML データ型としてネイティブに保存 :
データの保存には、階層、ドキュメントの順序、要素と属性の値など、データの XML コンテンツを保持する内部表現が使用されます。 具体的には、XML データの InfoSet コンテンツが保存されます (InfoSet の詳細については、http://www.w3.org/TR/xml-infoset
(英語) を参照してください)。 意味のない空白、属性の順序、名前空間のプレフィックス、および XML 宣言などは無視されるので、InfoSet は XML の正確なコピーにはならない場合があります。
XML データ型に型が指定されている (つまり、XML スキーマが適用されている) 場合、InfoSet に型情報を追加する PSVI (post-schema validation Infoset) が内部表現にエンコードされます。 その結果、解析の速度が格段に向上します。 (詳細については、http://www.w3.org/TR/xmlschema-1
)
-
XML とリレーショナル ストレージとのマッピング :
注釈付きスキーマ (AXSD) を使用して、XML を 1 つ以上のテーブルの列に分解します。この際、要素間の順序および再帰スキーマは無視されますが、階層構造は保持されるので、リレーションは忠実に再現されます。
-
大きなオブジェクトの保存 ([n]varchar(max) および varbinary(max)):
データの正確なコピーが格納されます。 これは特殊な目的のアプリケーション (法務文書など) に適しています。 大部分のアプリケーションでは正確なコピーは必要なく、XML コンテンツ (InfoSet の再現性) で十分です。
通常は、上記のアプローチを組み合わせて使用します。 たとえば、XML データを XML データ型の列に保存し、プロパティをリレーション列に昇格させることができます。 または、マッピング テクノロジを使用して、データの再帰箇所のみを XML データ型の列に保存できます。
ネイティブ XML テクノロジ
XML データは、サーバーの XML データ型の列に保存できます。 保存は、次のような場合に行います。
-
サーバーに XML データを簡単に保存する場合。
-
XML データのスキーマの有無がはっきりしない場合。
-
データ内のドキュメントの順序を保持する必要がある場合。
-
XML データへのクエリおよび変更を行う場合。
-
クエリ処理を高速化するために、XML データにインデックスを付ける場合。
-
元になるテーブルに対する Transact-SQL アプリケーションの稼動を停止させることなく、既存のリレーショナル データから XML データ型の値を生成する場合。 ただし、生成した XML を変更してもリレーショナル データは更新されません。
-
XML データおよび XML スキーマを管理するシステム メタデータ ビューがアプリケーションに必要な場合。
XML ドキュメントの構造にさまざまなバリエーションがある場合、XML ドキュメントによって準拠しているスキーマが異なる場合、またはスキーマが複雑でリレーション構造へのマップが困難な場合に、ネイティブ XML 保存が役立ちます。
例 : XML データ型を使用した XML データのモデル化
各トピックごとに章が立てられ、各章が複数の節から構成されている XML 形式の製品マニュアルがあるとします。 節の下位には小節がある場合があり、これは再帰的な要素です。 製品マニュアルは、多数の各種コンテンツ、図版、および技術的な数値から構成されています。 ユーザーは、興味のあるトピックを検索したり、技術的な数値に対してクエリを実行することができます。 データは半構造化されています。 XML ドキュメントを XML データ型の列に保存するデータ モデルが適しています。 このデータ モデルでは、XML データの InfoSet コンテンツが保持されます。 XML 列にインデックスを付けることで、クエリのパフォーマンスが向上します。
例 : XML データの正確なコピーを保持
政府の規制により、XML ドキュメントのテキスト (署名書類、法務文書、株取引の注文書など) の正確なコピーが必要だとします。 頻繁にはクエリおよび変更を行わない場合、ドキュメントは [n]varchar(max) 列に保存できます。
クエリを行うため、実行時にデータを XML データ型に変換します。 この変換は、負荷が高いので注意してください。 クエリを頻繁に実行する場合、ドキュメントを XML データ型の列にも重複して保存できます。 XML 列に XML のインデックスを作成することが可能ですが、[n]varchar(max) 列の正確なコピーを返すこともできます。
XML 列は、[n]varchar(max) 列に基づいて計算することができます。 ただし、計算された XML 列に XML インデックスを作成することも、[n]varchar(max) 列や varbinary(max) 列に XML インデックスを構築することもできません。
XML ビュー テクノロジ
XML スキーマとデータベースのテーブルとのマッピングを定義できます。 これにより、データの "XML ビュー" が定義されます。 XML ビューにクエリを実行するには XPath 1.0 を使用できますが、この際、クエリは元になるテーブルに対する SQL クエリに変換されます。 同様に、XML ビューを使用した更新は、元になるテーブルにも反映されます。
このテクノロジは、以下のような場合に役立ちます。
-
既存のリレーショナル データに対して、XML を使用する XML 主体のプログラミング モデル (アップデートグラム、XPath 1.0 など) が必要な場合。
-
XML データに対するスキーマ (XSD、XDR) が既にある場合。 スキーマは、外部のパートナーから提供されたものでもかまいません。
-
データの順序が重要でない場合、またはクエリを実行できるデータが再帰になっていない場合。
-
XPath 1.0 およびアップデートグラムを使用して、XML ビューからデータのクエリおよび変更を実行する場合。
-
XML データの一括読み込みおよび元になるテーブルへの分解を行う場合。
例 : 注釈付き XML スキーマ (AXSD) を使用したデータ モデリング
XML として操作したいリレーショナル データが既にあるとします。 リレーショナル データに対し、AXSD を使用して XML ビューを定義します。 この XML ビューによって、XML データをテーブルに一括読み込みし、元になるリレーショナル データへのクエリや更新を XML ビューを使用して実行できます。 このモデルが役立つのは、SQL アプリケーションの稼動を停止することなく、データを別のアプリケーションと交換する場合です。
例には、データ交換用の XML として公開されているリレーショナル データ、および固定のスキーマを持つ XML データが含まれます。
リレーショナル列を使用した XML のモデル化
リレーショナル列と XML データ型の列の組み合わせが、データ モデリングに適している場合がよくあります。 XML データから取り出した値の中には、リレーショナル列に保存できるものもありますが、それ以外の値や XML 値全体は、XML データ型の列に保存されます。 その結果、パフォーマンスが向上する場合があります (たとえば、リレーショナル列に作成したインデックスを完全に制御できるなど)。 ただし、データ保存を管理する責任は大きくなります。
リレーショナル列に保存する値は、ワークロードに応じて選択してください。 たとえば、パス式 /Customer/@CustId を基に XML 値全体を取得する場合、CustId 属性の値をリレーショナル列に昇格させ、インデックスを付けることで、パフォーマンスが向上することがあります。 一方で、XML データを分解しすぎると、再構築の負荷が大きくなります。
XML データが高度に構造化されている場合 (たとえば、テーブルのコンテンツが XML に変換されているなど)、すべてのデータをリレーショナル列にマップできます。
XML データ型を使用したデータ モデリング
同じテーブルでも、別のテーブルでも
XMLデータ型の列は、リレーショナル列を別に持つテーブル、またはメインのテーブルと外部キーでリレーションが設定された別のテーブルに作成できます。
以下の条件のいずれかを満たしている場合、XML データ型の列は既存のテーブルに作成します。
以下の条件を満たしている場合は、 XML データ型の列を別のテーブルに作成します。
XML データ型の、型指定の有無と制限
型が指定されていない XML データ型の列には、整形式のあらゆる XML を保存できます。 データが整形式かどうかはチェックされますが、XML スキーマを列と関連付ける必要はありません。 このことは、型が指定されていない XML 変数およびパラメータにも当てはまります。
使用している XML データについて記述した XML スキーマがある場合、型情報を使用してデータの保存とクエリ処理を検証および最適化できます。
以下の条件を満たす場合は、型指定されていない XML データ型を使用します。
以下の条件を満たす場合は、型指定されている XML データ型を使用します。
XML 列に型を指定する以外に、XML データ型の列には、型指定の有無にかかわらずリレーションの (列または行の) 制約を適用できます。 次の条件を満たす場合、制約を適用します。
-
XML スキーマで捕捉されていない XML データの制約がある場合。 たとえば、配達先住所が事業所から 50 マイル以内かどうかを確認するような場合です。 制約には、XML データ型のメソッドが必要になる場合があります。
-
テーブルの別の列 (XML 列かどうかは問いません) が制約に関与する場合。 たとえば、XML インスタンスで検出された顧客 ID (/Customer/@CustId) がリレーショナル列 CustomerID の値と同一かどうかを確認する場合です。
-
型が指定されていない XML 列に保存されているデータが複数の XML に準拠している場合。 制約を使用することで、それぞれの XML 値が適切な XML スキーマに応じて検証されます (たとえば、書籍の情報は書籍用の XML スキーマに従って検証され、DVD の情報は DVD 用のスキーマに従って検証されるなどです)。
インライン ドキュメント型定義 (DTD)
XML データ型の列、変数、およびパラメータは、XML スキーマを使用して型を指定できます。 外部の DTD で型を指定することはできません。 ただし、インライン DTD を使用すると、型指定の有無にかかわらず XML データ型に既定値を設定したり、エンティティ参照を拡張形式に置き換えたりすることができます。
DTD から XML スキーマ ドキュメントへの変換、およびデータベースへの XML スキーマの読み込みに、サードパーティのツールを使用できます。
XML データ型の列へのインデックス設定
XML インデックス
次の条件を満たす場合、XML データ型の列の XML インデックスが有用となる場合があります。
例 : XML インデックスの作成
次のステートメントを実行すると、テーブル T の XML 列 xCol に idx_xCol という XML インデックスが作成されます。
CREATE XML INDEX idx_xCol on T (xCol)
フルテキスト インデックス
XML データ型の列にはフルテキスト インデックスを作成できます。これにより、構造を無視して XML 値のコンテンツにインデックスが付けられます。 属性値にはフルテキスト インデックスが付けられません。 状況によっては、フルテキスト検索と XML インデックスの使用を組み合わせることができます。
例 : フルテキスト検索と XML クエリの組み合わせ
XML 列にフルテキスト インデックスを作成したら、XML 値が書名に語 "custom" を含んでいることを次のクエリにより確認します。
SELECT *
FROM T
WHERE CONTAINS(xCol,'custom')
AND xCol::exist('/book/title/text()[contains(.,"custom")]') =1 CONTAINS() メソッドでは、フルテキスト インデックスを使用して、ドキュメントの任意の場所に語 "custom" を含む XML 値をサブセットとして取り出しています。 exist() 句で、書名に語 "custom" が出現している値を絞り込んでいます。
CONTAINS() を使用するフルテキスト検索と、XQuery contains() は、意味合いが異なります。 前者が語幹検索を使用したトークンの照合であるのに対し、後者はサブ文字列の照合です。 したがって、上記のクエリは書名の語 "customizable" にはヒットしません (フルテキストの CONTAINS() が失敗します)。 しかし、"run" を検索した場合、"run"、"runs"、および "running" はいずれもヒットします。 純粋なサブ文字列の検索を実行する場合、通常はフルテキストの CONTAINS() 句を削除してください。
さらに、フルテキスト検索では語幹検索が利用されますが、XQuery contains() では文字どおりの語句の検索が行われます。 この違いを、次の例で示します。
例 : 語幹検索を使用した XML 値のフルテキスト検索
「例 : フルテキスト検索と XML クエリの組み合わせ」の XQuery contains() のチェックは、通常は削除できません。次のクエリを考えてみましょう。
SELECT *
FROM T
WHERE CONTAINS(xCol,'run')
XQuery を使用して検索コンテキストがチェックされることはありません。 さらに、ドキュメント内の語 "ran" は、語幹検索によって検索条件にヒットします。
フルテキスト インデックスが付けられた、AXSD を使用するリレーショナル列に XML を分解すると、XML ビューに対して XPath クエリを実行しても元になるテーブルへのフルテキスト検索は実行されません。
プロパティの昇格
クエリを主に少数の要素や属性の値に対して実行する場合 (たとえば、最終更新日など)、その数値をリレーショナル列に昇格できます。 XML データのごく一部にクエリを発行し、XML インスタンス全体を取得する場合 (たとえば、/Customer/@CustId の値を指定して、顧客 ID を基に顧客を検索する場合) に、この方法が役立ちます。 そのような場合、XML 列に XML インデックスを作成するほどの必要はなく、昇格させた列にインデックスを作成できます。 クエリを記述するときは、昇格させた列を使用するように (つまり、クエリ オプティマイザが XML 列のクエリの対象を計算列に再設定しないように) する必要があります。
昇格させた列は計算列として同じテーブルまたはインデックス付きのビューに作成できます。 これは、各 XML インスタンスから単一値 (つまり、値が 1 つだけのプロパティ) を昇格するときに適しています。 ただし、値が複数のプロパティの場合、以下に示すようにそのプロパティ用のテーブルを別に作成する必要があります。
XML データ型を基にした計算列
XML データ型のメソッドを呼び出すユーザー定義関数 (UDF) を使用して、計算列を作成できます。 計算列の型は SQL 型であれば、XML を含めてどの型でもかまいません。 このことを、次の例で示します。
例 : XML データ型のメソッドを基にした計算列
顧客 ID 用のユーザー定義関数を作成します。
CREATE FUNCTION udf_get_Customer_id (@xData xml)
RETURNS int
BEGIN
DECLARE @CustId
SELECT @CustId = @xData::value('/Customer[1]/@CustId', 'int')
RETURN @CustId
END
GO 整数型の計算列 CustId をテーブルに追加します。
ALTER TABLE T
ADD CustId AS dbo.udf_get_CustId(xCol)
GO
計算列にインデックスを付けることができます。
例 : XML データ型のメソッドを基にした計算列に対するクエリ
顧客 ID が 123 の顧客を取得するクエリは次のとおりです。
SELECT xCol
FROM T
WHERE xCol::exist ('/Customer[1]/@CustId = 123') = 1 このクエリは、計算列を使用して、次のように書き換えることができます。
SELECT xCol
FROM T
WHERE CustId = 123
XML データ型を返すユーザー定義関数、およびその UDF を使用する計算列を作成できます。 ただし、計算 XML 列には XML インデックスを作成できません。
XML データ型を基にインデックスが設定されたビュー
XMLデータ型のメソッドを使用したユーザー定義関数を使用して、インデックス付きのビューに列を作成できます。 その例を次に示します。
例 : XML データ型のメソッドを基にインデックスが付けられたビュー
次のビュー定義により、2 つの列を持つビューが作成されます。列の 1 つは元になるテーブル T の主キー、もう 1 つは顧客 ID です。
CREATE VIEW V AS
SELECT pk, dbo.udf_get_CustId(xCol)
FROM T
このビュー定義には、「例 : XML データ型のメソッドを基にした計算列」で定義したユーザー定義関数 udf_get_CustId() が使用されています。 インデックス付きビューの最初のインデックスは、クラスタ化インデックスである必要があります。
CREATE CLUSTERED INDEX idx_V ON V(pk)
インデックス付きビューには、それ以外の非クラスタ化インデックスも作成できます。
先ほどの例では、インデックス付きビューに対してクエリを直接記述する必要がありました。 クエリ オプティマイザによって、XML 列のクエリの対象がインデックス付きのビューに再設定されることはありません。
プロパティ テーブルの作成
XMLデータの複数の値を持つプロパティの一部を、別のテーブルに昇格させることができます。さらに、そのテーブルにインデックスを作成し、インデックス付きテーブルを使用するようにクエリの対象を再設定できます。 一般的なシナリオとして、少数のプロパティがクエリのワークロードの大部分で使用されている場合があります。
以下のことを実行できます。
例 : プロパティ テーブルの作成
create table tblProp (colFK int, colIXKey varchar(max))
GO
例 : XML ドキュメントをリレーショナル行セットに変換するユーザー定義関数の作成
create function udf_XML2Table (@pk varchar(100), @xCol xml)
returns @ret_Table table (colFK int, colIXKey varchar(max))
with schemabinding
as
begin
insert into @ret_Table
select @pk, @xCol::value('.', 'varchar(30)', R.noderef)
from (select noderef from XMLNODEREFS(@xCol,
'/Customer/Phone')) R
return
end
go 例 : プロパティ テーブルを保持して挿入トリガを作成
create trigger trg_docs_INS
on docs
for insert
as
declare @wantedXML xml
declare @FK int
select @wantedXML = xdoc::query('//link') from inserted
select @FK = PK from inserted
insert into tblProp
select * from dbo.udf_XML2Table(@FK, @wantedXML)
go 例 : プロパティ テーブルを保持して削除トリガを作成
create trigger trg_docs_DEL
on docs
for delete
as
declare @FK int
select @FK = PK from deleted
delete tblProp where colFK = @FK
go
例 : 副テーブルを保持して更新トリガを作成
create trigger trg_docs_UPD
on docs
for update
as
if update(xDoc) or update(PK)
begin
declare @FK int
declare @wantedXML xml
select @FK = PK from deleted
delete tblProp where colFK = @FK
select @wantedXML = xDoc::query('//link') from inserted
select @FK = PK from inserted
insert into tblProp
select * from dbo.udf_XML2Table(@FK, @wantedXML)
end
go 例 : プロパティ テーブルへのクエリ
select * from tblProp
go
使用法
Value()、XmlNodeRefs()、および OpenXML()
SELECT 句で XML データ型に対し value() 関数を使用して、行セットを生成できます。 行セットの列数が多い場合、または行セットを生成するパス式が複雑な場合、あるいはその両方を満たす場合、内部参照メカニズムを使用すると、効率的になることがあります。 XmlNodeRefs() から、XML データ型に対する query() 関数、value() 関数、および exist() 関数に使用できる XML インスタンス内の参照が生成されます。 XmlNodeRefs() からはさらに、XML データ型インスタンスの有効な XML ノードごとに行が 1 行ずつ生成されます。
例 : XmlNodeRefs の使用
1999 年以降に生産された自動車のメーカーの値を、Brand と Year という 2 つの列から構成される行セットととして取り出すとします。 これを実現するには、次のように XmlNodeRefs() および value() を使用します。
CREATE TABLE ##tmpCar (xmlcol XML)
INSERT INTO ##tmpCar VALUES (
'<cars>
<car>
<brand>Ford</brand>
<year>2000</year>
</car>
<car>
<brand>Toyota</brand>
<year>2002</year>
</car>
</cars>'
)
Select xmlcol::value('brand', 'nvarchar(50)', nref) Brand,
xmlcol::value('year', 'int', nref) Year
From ##tmpCar T
cross apply
(select * from xmlnoderefs(T.xmlcol, '//car')) AS R(nref)
Where xmlcol::exist('year[text() > 1999]', nref)=1 上記の例では、XmlNodeRefs によって、XML 値ごとに参照の行セットが生成されています。 各参照は、<car> 要素を参照しています。 この参照との相対パス式を評価することで、車の商標名と年を取得します。
SQL Server 2000 には、OpenXml() を使用して XML 値から行セットを生成する機能が提供されています。 それにより、行セットのリレーショナル スキーマ、および XML データの値を行セットの列にマップする方法を指定できます。
例 : XML データ型に OpenXml() を使用
先ほどの例のクエリを考えてみます。 OpenXml() を使用して、次のように書き換えることができます。
DECLARE cars_cursor CURSOR
FOR
SELECT xCol
FROM ##tmpCar
OPEN cars_cursor
DECLARE @xmlVal XML
DECLARE @idoc int
FETCH NEXT FROM cars_cursor INTO @xmlVal
WHILE (@@FETCH_STATUS = 0)
BEGIN
EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlVal
SELECT *
FROM OPENXML (@idoc, '//car')
WITH (Brand varchar(10) 'maker/text()',
Year int 'year/text()') R
WHERE R.Year > 1999
EXEC sp_xml_removedocument @idoc
FETCH NEXT FROM cars_cursor INTO @xmlVal
END
CLOSE cars_cursor
DEALLOCATE cars_cursor
OpenXml() を実行するとメモリ内での表現が作成され、クエリ プロセッサの代わりに作業用テーブルが使用されます。 このクエリ プロセッサは、XQuery エンジンではなく MSXML 3.0 の XPath 1.0 プロセッサに依存しています。 作業用テーブルは、同一の XML インスタンスで OpenXml() を複数回呼び出しても、共有されることはありません。 そのため、スケーラビリティが制限されます。 OpenXml() により、WITH 句が指定されていないときには、XML データのエッジ テーブル フォーマットを利用できます。 また、残りの XML 値は、独立した "オーバーフロー" 列で使用できます。
XmlNodeRefs() 関数と value() 関数を組み合わせることで、XML インデックスを効率的に使用できます。 したがって、OpenXml よりも、パフォーマンスとスケーラビリティが優れています。
FOR XML による行セットからの XML 生成
FOR XML を新しい TYPE ディレクティブと共に使用して、行セットから XML データ型のインスタンスを生成できます。
結果は、XML データ型の列、変数、またはパラメータに割り当てることができます。 また、FOR XML は入れ子にすることで階層構造を作ることができます。 FOR XML を入れ子にする方が FOR XML EXPLICIT よりも記述が容易ですが、階層が深い場合には FOR XML EXPLICIT ほどのパフォーマンスを得られない場合があります。
FOR XML TYPE を使用すると、SQL 構文でリレーショナル データに対して読み取り専用の XML ビューを定義できます。 このビューに対しては、次の例に示すように、SQL ステートメントおよび埋め込み XQuery を使用してクエリを実行できます。 たとえば、このような SQL ビューはストアド プロシージャで参照できます。
例 : 生成した XML データ型を返す SQL ビュー
次の SQL ビュー定義は、リレーショナル列 (pk) および XML 列から取得した書名から、XML ビューを作成します。
CREATE VIEW V (xmlVal) AS
SELECT pk, xCol::query('/book/title')
FROM T
FOR XML AUTO, TYPE ビュー V には、xmlVal という列のみの行が 1 行表示されます。このビューには、通常の方法でクエリを実行できます。 たとえば、次のクエリは "Database Theory" という書名の本を返します。
SELECT xmlVal::query('//book[title/text() = "Database Theory"]')
FROM V SQL ビュー定義は、注釈付きスキーマを使用して作成した XML ビューとほぼ似ています。 ただし、重要な違いがあります。 SQL ビュー定義は読み取り専用であり、操作するには埋め込みの XQuery を使用する必要があります。注釈付きスキーマを使用する XML ビューはそうではありません。 さらに、SQL ビューでは XQuery 式を適用する前に XML の結果が生成されますが、XML ビューの XPath クエリでは、元になるテーブルに対する SQL クエリが評価されます。
異領域へのクエリ
リレーショナル列と XML データ型の列が組み合わされた状態でデータを格納している場合、リレーショナル列および XML 列への処理を組み合わせたクエリを記述できます。 たとえば、FOR XML を使用してリレーショナル列および XML 列のデータを XML データ型のインスタンスに変換し、それに対して XQuery でクエリを実行できます。 逆に、XML 値から行セットを生成して (「使用法」を参照してください)、それに対し T-SQL でクエリを実行することもできます。
異領域へのクエリをより使いやすく効率的に記述するには、XQuery または XML DML 式で、SQL 変数や列の値を使用します。
XML スキーマへのクエリ
データベースに読み込んだ XML スキーマにクエリを実行する場合、次の方法で行うことができます。
-
組み込み関数 XML_SCHEMA_NAMESPACE (namespace-uri) を使用して、対象となる名前空間 namespace-uri が XML スキーマを表す XML データ型のインスタンスを生成します。 このインスタンスには、XML データ型関数を適用できます。 ただし、元になる XML スキーマの変更はできません。
-
XML スキーマ名前空間にカタログ ビューを使用します。
-
XML スキーマを保存するための XML データ型の列があるテーブルを作成し、XML 型のシステムに読み込みます。 XML 列には、XML データ型のメソッドを使用してクエリを実行できます。 さらに、この列には XML インデックスを作成できます。 ただし、XML 列と XML 型のシステムで、XML スキーマの整合性を維持するのはユーザーしだいです。 たとえば、XML スキーマ名前空間を XML 型のシステムから切り離す場合は、ユーザーが整合性維持のためテーブルからも切り離す必要があります。
例 : 登録されている XML スキーマ名前空間をカタログ ビューから取得
次のクエリを使用して、カタログ ビュー sys.xml_namespaces から、データベースに登録されている XML スキーマ名前空間を取得できます。
SELECT name
FROM sys.xml_namespaces
対象の名前空間 URI とその内部 ID から構成された 2 つの列を持つ行セットが返されます。
例 : XML スキーマ コンポーネントの取得
名前空間 URI http://www.microsoft.com/books の "first-name" 要素の定義を XML データとして取得するクエリを次に示します。
SELECT XML_SCHEMA_NAMESPACE(N'http://www.microsoft.com/books'):: query('//xs:element[@name="first-name"]') このクエリは、通常、XML スキーマのカタログ ビューに対するクエリを記述するよりも便利です。