クライアント側とサーバー側の XML 書式設定 (SQLXML 4.0)
ここでは、SQLXML における、クライアント側とサーバー側の XML 書式設定の一般的な違いについて説明します。
クライアント側の書式設定では複数の行セット クエリがサポートされない
複数の行セットを生成するクエリは、クライアント側の XML 書式設定を使用するときにはサポートされません。たとえば、クライアント側の書式設定が指定されている仮想ディレクトリがあるとし、次のサンプル テンプレートを考えてみます。このテンプレートの <sql:query> ブロックには 2 つの SELECT ステートメントがあります。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query>
SELECT FirstName FROM Person.Person FOR XML Nested;
SELECT LastName FROM Person.Person FOR XML Nested
</sql:query>
</ROOT>
このテンプレートはアプリケーション コードで実行できます。実行すると、クライアント側の XML 書式設定では複数の行セットの書式設定がサポートされていないため、エラーが返されます。2 つの別の <sql:query> ブロックにクエリを指定すると、必要な結果を得られます。
クライアント側とサーバー側の XML 書式設定では timestamp 型のマッピングが異なる
サーバー側の XML 書式設定では、XMLDATA オプションがクエリで指定される場合、timestamp 型のデータベース列が i8 XDR 型にマップされます。
クライアント側の XML 書式設定では、バイナリの base64 オプションがクエリで指定されているかどうかに従って、timestamp 型のデータベース列が uri または bin.base64 XDR 型にマップされます。bin.base64 XDR 型は SQL Servertimestamp 型に変換されるので、アップデートグラムや一括読み込み機能を使用するときに便利です。この方法で、挿入、更新、または削除操作が成功します。
サーバー側の書式設定ではサブタイプの VARIANT 型も使用される
サーバー側の XML 書式設定では、サブタイプの VARIANT 型も使用されます。クライアント側の XML 書式設定を使用する場合、variant は Unicode 文字列に変換され、サブタイプの VARIANT は使用されません。
NESTED モードと AUTO モード
クライアント側の FOR XML の NESTED モードは、サーバー側の FOR XML の AUTO モードに似ていますが、次の点が異なります。
サーバー側で AUTO モードを使用してビューにクエリを実行すると、ビュー名が結果の XML 内の要素名として返されます。
たとえば、AdventureWorks2008R2 データベースの Person.Person テーブルに次のビューが作成されるとします。
CREATE VIEW ContactView AS (SELECT BusinessEntityID as CID,
FirstName as FName,
LastName as LName
FROM Person.Person);
次のテンプレートでは、ContactView ビューに対するクエリと、サーバー側の XML 書式設定が指定されています。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query client-side-xml="0">
SELECT *
FROM ContactView
FOR XML AUTO
</sql:query>
</ROOT>
テンプレートを実行すると、次の XML が返されます。ここでは一部の結果のみが表示されています。クエリの実行対象のビューの名前が要素名になっていることに注意してください。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<ContactView CID="1" FName="Gustavo" LName="Achong" />
<ContactView CID="2" FName="Catherine" LName="Abel" />
...
</ROOT>
クライアント側の書式設定を、対応する NESTED モードで指定すると、ベース テーブル名が結果の XML 内の要素名として返されます。たとえば、次のテンプレートは前のテンプレートを変更したもので、同じ SELECT ステートメントが実行されますが、XML 書式設定はクライアント側で実行されます。つまり、このテンプレートでは client-side-xml が true に設定されています。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query client-side-xml="1">
SELECT *
FROM ContactView
FOR XML NESTED
</sql:query>
</ROOT>
このテンプレートを実行すると、次の XML が生成されます。この場合、ベース テーブル名が要素名になっていることに注意してください。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<Person.Person CID="1" FName="Gustavo" LName="Achong" />
<Person.Person CID="2" FName="Catherine" LName="Abel" />
...
</ROOT>
サーバー側の FOR XML を AUTO モードで使用すると、クエリで指定されたテーブルの別名が、結果の XML 内の要素名として返されます。
たとえば、次のテンプレートを考えてみます。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query client-side-xml="0">
SELECT FirstName as fname,
LastName as lname
FROM Person.Person AS C
FOR XML AUTO
</sql:query>
</ROOT>
このテンプレートを実行すると、次の XML が生成されます。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<C fname="Gustavo" lname="Achong" />
<C fname="Catherine" lname="Abel" />
...
</ROOT>
クライアント側の FOR XML を NESTED モードで使用すると、テーブル名が、結果の XML 内の要素名として返されます。クエリで指定されたテーブルの別名は使用されません。たとえば、次のテンプレートを考えてみます。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query client-side-xml="1">
SELECT FirstName as fname,
LastName as lname
FROM Person.Person C
FOR XML NESTED
</sql:query>
</ROOT>
このテンプレートを実行すると、次の XML が生成されます。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<Person.Person fname="Gustavo" lname="Achong" />
<Person.Person fname="Catherine" lname="Abel" />
...
</ROOT>
列を dbobject クエリとして返すクエリでは、これらの列に対して別名は使用できません。
たとえば、次のテンプレートを考えてみます。このテンプレートには、製品写真 ID と写真を返すクエリが含まれています。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query client-side-xml="1">
SELECT ProductPhotoID, LargePhoto as P
FROM Production.ProductPhoto
WHERE ProductPhotoID=5
FOR XML NESTED, elements
</sql:query>
</ROOT>
このテンプレートを実行すると、Photo 列が dbobject クエリとして返されます。この dbobject クエリでは、@P で存在しない列名が参照されています。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<Production.ProductPhoto>
<ProductPhotoID>5</ProductPhotoID>
<LargePhoto>dbobject/Production.ProductPhoto[@ProductPhotoID='5']/@P</LargePhoto>
</Production.ProductPhoto>
</ROOT>
XML 書式設定がサーバーで実行される場合 (client-side-xml="0")、dbobject クエリを返す列に別名を使用できます。dbobject クエリでは、別名を指定していても、実際のテーブル名と列名が返されます。たとえば、次のテンプレートではクエリが実行され、サーバー側の XML 書式設定が実行されます。ここでは client-side-xml オプションは指定されておらず、仮想ルートに Run On Client オプションは選択されていません。このクエリでは、クライアント側の NESTED モードではなく AUTO モードも指定されています。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query
SELECT ProductPhotoID, LargePhoto as P
FROM Production.ProductPhoto
WHERE ProductPhotoID=5
FOR XML AUTO, elements
</sql:query>
</ROOT>
このテンプレートを実行すると、次の XML ドキュメントが返されます。LargePhoto 列に対する dbobject クエリでは、別名が使用されていないことに注意してください。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<Production.ProductPhoto>
<ProductPhotoID>5</ProductPhotoID>
<LargePhoto>dbobject/Production.ProductPhoto[@ProductPhotoID='5']/@LargePhoto</LargePhoto>
</Production.ProductPhoto>
</ROOT>
クライアント側とサーバー側の XPath
クライアント側の XPath とサーバー側の XPath は類似していますが、次の点が異なります。
クライアント側の XPath クエリを使用するときに適用されるデータ変換は、サーバー側の XPath クエリを使用するときに適用されるものとは異なります。クライアント側の XPath では、CONVERT モード 126 の代わりに CAST が使用されます。
テンプレートで client-side-xml="0" (false) を指定すると、サーバー側の XML 書式設定を要求することになります。したがって、サーバーでは NESTED オプションが認識されないので、FOR XML NESTED は指定できません。指定するとエラーが生成されます。この場合、サーバーで認識される AUTO、RAW、または EXPLICIT モードを使用する必要があります。
テンプレートで client-side-xml="1" (true) を指定すると、クライアント側の XML 書式設定を要求することになります。この場合、FOR XML NESTED を指定できます。FOR XML AUTO を指定すると、client-side-xml="1" がテンプレートで指定されていても、サーバー側で XML 書式設定が行われます。