クライアント側とサーバー側の XML 書式設定 (SQLXML 4.0)
適用対象: SQL Server Azure SQL Database Azure SQL Managed Instance
ここでは、SQLXML における、クライアント側とサーバー側の XML 書式設定の一般的な違いについて説明します。
クライアント側の書式設定では複数の行セット クエリがサポートされない
複数の行セットを生成するクエリは、クライアント側の XML 書式設定を使用するときにはサポートされません。 たとえば、クライアント側の書式設定が指定されている仮想ディレクトリがあるとし、 <sql:query> ブロックに 2 つの SELECT ステートメントがあるこのサンプル テンプレートを考えてみましょう。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:query>
SELECT FirstName FROM Person.Contact FOR XML Nested;
SELECT LastName FROM Person.Contact FOR XML Nested
</sql:query>
</ROOT>
このテンプレートはアプリケーション コードで実行できます。実行すると、クライアント側の XML 書式設定では複数の行セットの書式設定がサポートされていないため、エラーが返されます。 2 つの個別の <sql:query> ブロックでクエリを指定すると、目的の結果が得られます。
クライアント側とサーバー側の XML 書式設定では timestamp 型のマッピングが異なる
サーバー側の XML 形式では、 timestamp 型のデータベース列が i8 XDR 型にマップされます (XMLDATA オプションがクエリで指定されている場合)。
クライアント側の XML 形式では、 timestamp 型のデータベース列は、 uri または bin.base64 XDR 型にマップされます (バイナリ base64 オプションがクエリで指定されているかどうかによって異なります)。 bin.base64 XDR 型は、アップデートグラム機能と一括読み込み機能を使用する場合に便利です。この型は SQL Server timestamp 型に変換されるためです。 この方法で、挿入、更新、または削除操作が成功します。
サーバー側の書式設定ではサブタイプの VARIANT 型も使用される
サーバー側の XML 書式設定では、サブタイプの VARIANT 型も使用されます。 クライアント側の XML 書式設定を使用する場合、variant は Unicode 文字列に変換され、サブタイプの VARIANT は使用されません。
NESTED モードと AUTO モード
クライアント側の FOR XML の NESTED モードは、サーバー側の FOR XML の AUTO モードに似ていますが、次の点が異なります。
サーバー側で AUTO モードを使用してビューにクエリを実行すると、ビュー名が結果の XML 内の要素名として返されます。
たとえば、AdventureWorksdatabase の Person.Contact テーブルに次のビューが作成されているとします。
CREATE VIEW ContactView AS (SELECT ContactID as CID,
FirstName as FName,
LastName as LName
FROM Person.Contact)
次のテンプレートでは、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.Contact CID="1" FName="Gustavo" LName="Achong" />
<Person.Contact 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.Contact 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.Contact C
FOR XML NESTED
</sql:query>
</ROOT>
このテンプレートを実行すると、次の XML が生成されます。
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<Person.Contact fname="Gustavo" lname="Achong" />
<Person.Contact 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 クエリを返す列のエイリアスを使用できます (別名が指定されている場合でも)。 たとえば、次のテンプレートはクエリを実行し、サーバー上で XML 書式設定が行われます ( client-side-xml オプションは指定されておらず、仮想ルートに対して クライアントで実行 オプションは選択されていません)。 このクエリでは、クライアント側の 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 の書式設定が行われます。
参照
FOR XML のセキュリティに関する考慮事項 (SQLXML 4.0)
クライアント側の XML 書式設定 (SQLXML 4.0)
サーバー側の XML 書式設定 (SQLXML 4.0)