FOR XML を使用した XML の構築

SELECT クエリは、結果を行セットとして返します。必要に応じて、SQL クエリに FOR XML 句を指定することで、SQL クエリの結果を XML 形式で取得することができます。FOR XML 句は、最上位レベルのクエリとサブクエリのいずれでも使用できます。最上位レベルの FOR XML 句は、SELECT ステートメント内でのみ使用できます。サブ クエリでは、FOR XML 句を INSERT、UPDATE、DELETE ステートメント内で使用できます。また、代入ステートメントでも使用できます。

FOR XML 句には、次のモードのうち 1 つを指定します。

  • RAW

  • AUTO

  • EXPLICIT

  • PATH

RAW モードは SELECT ステートメントによって返された行セットの行 1 つにつき 1 つの <row> 要素を生成します。入れ子にした FOR XML クエリを作成することで、XML 階層を生成できます。

AUTO モードは、SELECT ステートメントがどのように指定されているかに基づき、帰納的な方法で入れ子になった結果の XML を生成します。生成される XML の構造については最小限の制御しか行えません。AUTO モードで帰納的に生成された XML 構造に対して、入れ子になった FOR XML クエリを作成し、XML 階層を生成することができます。

EXPLICIT モードでは、XML の構造をより厳密に制御することができます。属性や要素を自由に組み合わせて、XML の構造を決めることができます。このモードでは、クエリを実行した結果として生成される行セットに特定の形式を指定する必要があります。その後、この行セットの形式が、XML の構造にマップされます。EXPLICIT モードの利点は、属性と要素を自由に組み合わせることができる点です。また、ラッパーや入れ子にした複雑なプロパティを作成したり、スペースで区切られた値を作成したり (OrderID 属性に注文 ID 値の一覧を渡すなど)、混合コンテンツを作成することもできます。

ただし、EXPLICIT モードのクエリを記述する作業は複雑になることがあります。EXPLICIT モードを使用して階層を生成する代わりに、RAW、AUTO、または PATH モードの入れ子にした FOR XML クエリと TYPE ディレクティブを作成するなど、FOR XML の新しい機能を使用できます。このような入れ子にした FOR XML クエリでも、EXPLICIT モードで生成できる XML を作成することができます。詳細については、「入れ子になった FOR XML クエリ」および「FOR XML クエリの TYPE ディレクティブ」を参照してください。

PATH モードと FOR XML クエリの入れ子機能を組み合わせると、EXPLICIT モードと同等の柔軟性が得られます。

これらのモードは、モードが設定されたクエリの実行に限って有効です。後続のクエリの結果に影響は与えません。

COMPUTE BY 句と FOR BROWSE 句

COMPUTE BY 句または FOR BROWSE 句で使用されるどのような選択に対しても FOR XML は無効です。たとえば、次のクエリを実行するとエラーが発生します。

SELECT TOP 5 SalesOrderID, UnitPrice 
FROM Sales.SalesOrderDetail 
ORDER BY SalesOrderID COMPUTE SUM(UnitPrice) BY SalesOrderID
FOR XML AUTO

FOR XML 句とサーバー名

FOR XML 句を伴う SELECT ステートメントが、クエリの中で 4 つの部分から構成される名前を指定している場合、クエリがローカル コンピュータ上で実行されると、結果の XML ドキュメントにサーバー名は返されません。しかし、クエリがネットワーク サーバー上で実行されると、4 つの部分から構成される名前でサーバー名が返されます。

たとえば、次のクエリについて考えてみます。

SELECT TOP 1 LastName
FROM ServerName.AdventureWorks.Person.Contact
FOR XML AUTO

ServerName がローカル サーバーの場合、クエリは次の値を返します。

<AdventureWorks.Person.Contact LastName="Achong" />

ServerName がネットワーク サーバーの場合、クエリは次の値を返します。

<ServerName.AdventureWorks.Person.Contact LastName="Achong" />

次の別名を指定することによって、このような違いが生じないようにできます。

SELECT TOP 1 LastName
FROM ServerName.AdventureWorks.Person.Contact x
FOR XML AUTO 

このクエリの結果は次のようになります。

<x LastName="Achong"/>