xml データ型メソッドの使用に関するガイドライン

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

このトピックでは、xml データ型のメソッドの使用に関するガイドラインを説明します。

PRINT ステートメント

xml データ型メソッドは、次の例のように PRINT ステートメント内で使用することはできません。 xml データ型メソッドはサブクエリとして扱われますが、PRINT ステートメント内ではサブクエリの使用は認められていません。 このため、次の例ではエラーが返されます。

DECLARE @x XML
SET @x = '<root>Hello</root>'
PRINT @x.value('/root[1]', 'varchar(20)') -- will not work because this is treated as a subquery (select top 1 col from table)

解決方法の 1 つとしては、まず value() メソッドの結果を xml 型の変数に割り当ててから、この変数をクエリに指定します。

DECLARE @x XML
DECLARE @c VARCHAR(max)
SET @x = '<root>Hello</root>'
SET @c = @x.value('/root[1]', 'VARCHAR(11)')
PRINT @c

GROUP BY 句

xml データ型メソッドは、内部的にサブクエリとして扱われます。 GROUP BY はスカラーを必要とし、また、集計やサブクエリを許容しないため、GROUP BY 句には xml データ型メソッドは指定できません。 解決方法として、XML メソッドを内部で使用するユーザー定義関数を呼び出します。

エラーの報告

エラーが報告されると、xml データ型メソッドは次の形式で単一のエラーを生成します。

Msg errorNumber, Level levelNumber, State stateNumber:
XQuery [database.table.method]: description_of_error

次に例を示します。

Msg 2396, Level 16, State 1:
XQuery [xmldb_test.xmlcol.query()]: Attribute may not appear outside of an element

シングルトンの確認

実行時にシングルトンであることが確実かどうかをコンパイラで判断できない場合、シングルトンを必要とするロケーション ステップ、関数パラメーター、および演算子はエラーを返します。 型指定されていないデータではこの問題が頻繁に発生します。 たとえば、属性の参照には単一の親要素が必要ですが、 単一の親ノードを選択する序数があれば十分です。 node()-value() の組み合わせを評価して属性値を抽出するときは、序数を指定する必要がない場合もあります。 次の例を参照してください。

例:既知のシングルトン

次の例では、nodes() メソッドで <book> 要素ごとに個別の行が生成されます。 <book> ノードで評価される value() メソッドでは、@genre の値を抽出します。これは属性であり、シングルトンです。

SELECT nref.value('@genre', 'VARCHAR(max)') LastName
FROM T CROSS APPLY xCol.nodes('//book') AS R(nref)

型指定された XML の型の確認には XML スキーマが使用されます。 XML スキーマでノードがシングルトンとして指定されている場合、その情報がコンパイラで使用され、エラーは発生しません。 それ以外の場合、単一ノードを選択する序数が必要です。 特に、/book//title などの、descendant-or-self 軸 (//) を使用すると、XML スキーマでシングルトンが指定されていても <title> 要素のシングルトン カーディナリティ推定が失われます。 そのため、これを「(/book//title)[1]」と書き換える必要があります。

型の確認では、//first-name[1](//first-name)[1] の違いを常に認識することが重要です。 前者は兄弟の中で最も左の <first-name> ノードのみから構成される <first-name> ノードのシーケンスを返します。 後者は XML インスタンスのドキュメント順で最初のシングルトンの <first-name> ノードを返します。

例:value() の使用

型指定されていない XML 列に対し次のクエリを実行すると、静的なコンパイル エラーが発生します。value() の最初の引数はシングルトン ノードでなければなりませんが、<last-name> ノードが実行時に現れる回数が 1 回のみかどうかをコンパイラで判断できないためです。

SELECT xCol.value('//author/last-name', 'NVARCHAR(50)') LastName
FROM T

次のような解決策が考えられます。

SELECT xCol.value('//author/last-name[1]', 'NVARCHAR(50)') LastName
FROM T

しかし、各 XML インスタンスで <author> ノードが複数回現れる場合があるので、これではエラーは解決しません。 次のように書き換えると、正常に動作します。

SELECT xCol.value('(//author/last-name/text())[1]', 'NVARCHAR(50)') LastName
FROM T

このクエリは、各 XML インスタンスの最初の <last-name> 要素の値を返します。

参照