sp_describe_first_result_set (Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Microsoft Fabric の SQL 分析エンドポイントMicrosoft Fabric のウェアハウス

Transact-SQL バッチの可能性のある最初の結果セットのメタデータを返します。 バッチが結果を返さない場合は、空の結果セットを返します。 データベース エンジンが、静的分析を実行することで、実行される最初のクエリのメタデータを特定できない場合は、エラーが発生します。 動的管理ビュー sys.dm_exec_describe_first_result_set (Transact-SQL) は、同じ情報を返します。

Transact-SQL 構文表記規則

構文

  
sp_describe_first_result_set [ @tsql = ] N'Transact-SQL_batch'   
    [ , [ @params = ] N'parameters' ]   
    [ , [ @browse_information_mode = ] <tinyint> ] ]  

引数

[ @tsql = ] 'Transact-SQL_batch' 1 つ以上の Transact-SQL ステートメント。 Transact-SQL_batch には、nvarchar(n) または nvarchar(max) を指定できます。

[ @params = ] N'parameters' @params では、sp_executesql と同様に、Transact-SQL バッチのパラメーターの宣言文字列を指定します。 parameters には、nvarchar(n) または nvarchar(max) を指定できます。

Transact-SQL_batch に埋め込まれているすべてのパラメーターの定義が格納された 1 つの文字列です。 この文字列は Unicode 定数または Unicode 変数にする必要があります。 各パラメーター定義は、パラメーター名とデータ型で構成されます。 n は、追加のパラメーター定義を示すプレースホルダーです。 ステートメントで指定されているすべてのパラメーターが、@params で定義されている必要があります。 Transact-SQL ステートメントまたはステートメント内のバッチにパラメーターが含まれていない場合、@params は不要です。 このパラメーターの既定値は NULL です。

[ @browse_information_mode = ] tinyint 追加のキー列とソース テーブルの情報を返すかどうかを指定します。 1 に設定すると、各クエリは FOR BROWSE オプションがクエリに含まれているかのように分析されます。 追加のキー列とソース テーブル情報が返されます。

  • 0 に設定すると、情報は返されません。

  • 1 に設定すると、各クエリは FOR BROWSE オプションがクエリに含まれているかのように分析されます。 ベースのテーブル名がソース列情報として返されます。

  • 2 に設定すると、各クエリは、カーソルの準備または実行で使われるかのように分析されます。 ビュー名がソース列情報として返されます。

リターン コードの値

sp_describe_first_result_set は、成功すると常に 0 の状態を返します。 プロシージャが RPC として呼び出されていて、エラーをスローした場合、リターン状態には sys.dm_exec_describe_first_result_set の error_type 列に記述されているエラーの種類が設定されます。 プロシージャが Transact-SQL から呼び出されている場合は、エラーがあるときでも、戻り値は常にゼロになります。

結果セット

この共通メタデータは、結果のメタデータの各列に対する 1 行の結果セットとして返されます。 各行には、列の種類と NULL 値の許容属性が次のセクションに示す形式で記述されます。 各コントロールのパスに最初のステートメントが存在しない場合は、0 行の結果セットが返されます。

列名 データ型 説明
is_hidden bit NOT NULL その列が情報参照のために追加された余分な列であり、実際には結果セットに含まれないことを示します。
column_ordinal int NOT NULL 結果セット内の列の位置を示す序数を格納します。 最初の列の位置は 1 で指定されます。
name sysname NULL 列の名前を確認できる場合は、その名前を格納します。 そうでない場合は、NULL が含まれます。
is_nullable bit NOT NULL 列が NULL を許容する場合は 1、NULL を許容しない場合は 0、NULL を許可するかどうかわからない場合は 1 が格納されます。
system_type_id int NOT NULL sys.types で指定されている、列のデータ型の system_type_id が格納されます。 CLR 型の場合は、system_type_name 列が NULL を返しても、この列は値 240 を返します。
system_type_name nvarchar(256) NULL 列のデータ型に指定されている名前と引数 (長さ、有効桁数、小数点以下桁数など) を格納します。 データ型がユーザー定義の別名型の場合は、基になるシステム型がここで指定されます。 CLR ユーザー定義型の場合は、この列には NULL が返されます。
max_length smallint NOT NULL 列の最大長 (バイト単位) です。

-1 = 列のデータ型は、varchar(max)nvarchar(max)varbinary(max)、または xml です。

text 列の場合、max_length の値は、16 または sp_tableoption 'text in row' によって設定された値になります。
有効桁数 (precision) tinyint NOT NULL 数値ベースの場合は、列の有効桁数です。 それ以外の場合は 0 を返します。
scale tinyint NOT NULL 数値ベースの場合は、列の小数点以下桁数です。 それ以外の場合は 0 を返します。
collation_name sysname NULL 文字ベースの場合は、列の照合順序の名前です。 それ以外の場合は NULL を返します。
user_type_id int NULL CLR 型と別名型の場合、sys.types で指定された列のデータ型の user_type_id を格納します。 それ以外の場合は NULL です。
user_type_database sysname NULL CLR 型と別名型の場合、その型が定義されたデータベースの名前を格納します。 それ以外の場合は NULL です。
user_type_schema sysname NULL CLR 型と別名型の場合、その型が定義されたスキーマの名前を格納します。 それ以外の場合は NULL です。
user_type_name sysname NULL CLR 型と別名型の場合、その型の名前を格納します。 それ以外の場合は NULL です。
assembly_qualified_type_name nvarchar (4000) CLR 型の場合、その型を定義するアセンブリの名前とクラスを返します。 それ以外の場合は NULL です。
xml_collection_id int NULL sys.columns で指定された列のデータ型の xml_collection_id を格納します。 この列は、返される型が XML スキーマ コレクションに関連付けられていない場合は NULL を返します。
xml_collection_database sysname NULL この型に関連付けられている XML スキーマ コレクションが定義されているデータベースを格納します。 この列は、返される型が XML スキーマ コレクションに関連付けられていない場合は NULL を返します。
xml_collection_schema sysname NULL この型に関連付けられている XML スキーマ コレクションが定義されているスキーマを格納します。 この列は、返される型が XML スキーマ コレクションに関連付けられていない場合は NULL を返します。
xml_collection_name sysname NULL この型に関連付けられている XML スキーマ コレクションの名前を格納します。 この列は、返される型が XML スキーマ コレクションに関連付けられていない場合は NULL を返します。
is_xml_document bit NOT NULL 返されたデータ型が XML で、その型が XML フラグメントではなく完全な XML ドキュメント (ルート ノードを含む) であると保証される場合、1 を返します。 それ以外の場合は 0 を返します。
is_case_sensitive bit NOT NULL 列が大文字と小文字を区別する文字列型の場合は 1、それ以外の場合は 0 を返します。
is_fixed_length_clr_type bit NOT NULL 列が固定長の CLR 型の場合は 1、それ以外の場合は 0 を返します。
source_server sysname この結果内の列によって返された元のサーバーの名前です (リモート サーバーから発生する場合)。 sys.servers で指定されている名前です。 この列がローカル サーバー上で発生した場合、または元のサーバーを特定できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
source_database sysname この結果内の列によって返された元のデータベースの名前です。 データベースを特定できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
source_schema sysname この結果内の列によって返された元のスキーマの名前です。 スキーマを特定できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
source_table sysname この結果内の列によって返された元のテーブルの名前です。 テーブルを特定できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
source_column sysname 結果列から返された元の列の名前です。 列を特定できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
is_identity_column bit NULL この列が ID 列の場合は 1、それ以外の場合は 0 を返します。 ID 列であることを確認できない場合は NULL を返します。
is_part_of_unique_key bit NULL この列が一意インデックス (一意制約と主キー制約を含む) の一部である場合は 1、それ以外の場合は 0 を返します。 一意インデックスの一部であることを確認できない場合は NULL を返します。 参照情報が要求された場合にのみ設定されます。
is_updateable bit NULL この列が更新可能である場合は 1、それ以外の場合は 0 を返します。 更新可能であることを確認できない場合は NULL を返します。
is_computed_column bit NULL この列が計算列の場合は 1、それ以外の場合は 0 を返します。 計算列であることを確認できない場合は NULL を返します。
is_sparse_column_set bit NULL この列がスパース列の場合は 1、それ以外の場合は 0 を返します。 列がスパース列セットの一部であることを確認できない場合は、NULL を返します。
ordinal_in_order_by_list smallint NULL ORDER BY リストにおけるこの列の位置。 列が ORDER BY リストにない場合、または ORDER BY リストを一意に特定できない場合は、NULL を返します。
order_by_list_length smallint NULL ORDER BY リストの長さを返します。 ORDER BY リストがない場合、または ORDER BY リストを一意に特定できない場合は NULL を返します。 この値は、sp_describe_first_result_set によって返されるすべての行に対して同じであることに注意してください。
order_by_is_descending smallint NULL ordinal_in_order_by_list が NULL でない場合、order_by_is_descending 列には、この列の ORDER BY 句の方向がレポートされます。 それ以外の場合は、NULL が報告されます。
tds_type_id int NOT NULL 内部使用です。
tds_length int NOT NULL 内部使用です。
tds_collation_id int NULL 内部使用です。
tds_collation_sort_id tinyint NULL 内部使用です。

解説

sp_describe_first_result_set は、プロシージャが (架空の) バッチ A の最初の結果セットのメタデータを返し、その後でそのバッチ (A) が実行される場合に、バッチは (1) 最適化時エラーを発生させる、(2) 実行時エラーを発生させる、(3) 結果セットを返さない、または (4) sp_describe_first_result_set で記述されているものと同じメタデータを含む最初の結果セットを返すことを保証します。

名前、NULL 値の許容属性、およびデータ型が異なる可能性があります。 sp_describe_first_result_set が空の結果セットを返す場合、バッチ実行で結果セットが返されないことが保証されます。

この保証は、サーバーで関連スキーマが変更されないことを前提としています。 サーバーでの関連するスキーマの変更には、sp_describe_first_result_set が呼び出されてから、実行中に結果セットが返されるときまでに行われた、バッチ A での一時テーブルやテーブル変数の作成や、バッチ B によるスキーマ変更は含まれません。

sp_describe_first_result_set は、次のいずれかの場合にエラーを返します。

  • 入力の @tsql が、有効な Transact-SQL バッチでない場合。 有効性は、Transact-SQL バッチの解析と分析によって決定されます。 クエリの最適化中または実行中にバッチによってたエラーが発生しても、Transact-SQL バッチが有効かどうかを判断する際には考慮されません。

  • @paramsが NULL ではなく、パラメーターの宣言文字列として構文が有効ではない文字列が含まれている場合、またはいずれかのパラメーターを複数回宣言する文字列が含まれている場合。

  • 入力の Transact-SQL バッチで、@params で宣言されているパラメーターと同じ名前のローカル変数が宣言されている場合。

  • ステートメントで一時テーブルが使われている場合。

  • 後でクエリ実行の対象となる永続的なテーブルの作成が、クエリに含まれています。

他のチェックがすべて成功した場合、入力バッチ内で可能性のあるすべての制御フロー パスが考慮されます。 このとき、すべての制御フロー ステートメント (GOTO、IF/ELSE、WHILE、Transact-SQL TRY/CATCH ブロック) と、すべてのプロシージャ、動的 Transact-SQL バッチ、またはトリガー (EXEC ステートメント、DDL トリガーを発生させる DDL ステートメント、またはターゲット テーブルや、外部キー制約でのカスケード アクションのために変更されるテーブルでトリガーを発生させる DML ステートメントによって、入力バッチから呼び出されるもの) が考慮されます。 可能性のある制御パスが多い場合、ある時点でアルゴリズムが停止します。

各制御フロー パスに対して、結果セットを返す最初のステートメント (ある場合) が sp_describe_first_result_set によって特定されます。

バッチで可能性のある最初のステートメントが複数見つかった場合、その結果は、列の数、列の名前、NULL 値の許容、データ型で異なる場合があります。 これらの違いを処理する方法の詳細について、ここに記載します。

  • 列の数が異なる場合は、エラーがスローされ、結果は返されません。

  • 列の名前が異なる場合、返される列の名前は NULL に設定されます。

  • NULL 値の許容が異なる場合、返される NULL 値の許容では NULL が許可されます。

  • データ型が異なる場合は、次のケースを除き、エラーがスローされて、結果は返されません。

    • varchar(a) から varchar(a') (a' > a)。

    • varchar(a) から varchar(max)

    • nvarchar(a) から nvarchar(a') (a' > a)。

    • nvarchar(a) から nvarchar(max)

    • varbinary(a) から varbinary(a') (a' > a)。

    • varbinary(a) から varbinary(max)

sp_describe_first_result_set では、間接再帰はサポートされません。

アクセス許可

引数 @tsql を実行する権限が必要です。

一般的な例

A. 簡単な例

次の例では、1 つのクエリから返される結果セットについて説明します。

sp_describe_first_result_set @tsql = N'SELECT object_id, name, type_desc FROM sys.indexes'  

次の例では、パラメーターを含む 1 つのクエリから返される結果セットを示します。

sp_describe_first_result_set @tsql =   
N'SELECT object_id, name, type_desc   
FROM sys.indexes   
WHERE object_id = @id1'  
, @params = N'@id1 int'  

B. ブラウズ モードの使用例

次の 3 つの例では、異なるブラウズ情報モード間の主要な違いを示します。 クエリ結果には、関係する列だけが含まれています。

情報が返されないことを示す 0 を使用した例。

CREATE TABLE dbo.t (a int PRIMARY KEY, b1 int);  
GO  
CREATE VIEW dbo.v AS SELECT b1 AS b2 FROM dbo.t;  
GO  
EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM dbo.v', null, 0;  

結果セットは次のようになります。

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 b3 NULL NULL NULL NULL

クエリに FOR BROWSE オプションが含まれているかのように情報を返すことを示す 1 を使用した例。

EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM v', null, 1  
  

結果セットは次のようになります。

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 b3 dbo t B1 0
1 2 a dbo t a 1

カーソルを準備しているかのように分析することを示す 2 を使用した例。

EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM v', null, 2  

結果セットは次のようになります。

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 B3 dbo v B2 0
1 2 ROWSTAT NULL NULL NULL 0

C. 結果をテーブルに格納する

シナリオによっては、スキーマをさらに処理できるように、sp_describe_first_result_set プロシージャの結果を何らかのテーブルに入れておく必要があります。 まず、sp_describe_first_result_set プロシージャの出力と一致するテーブルを作成する必要があります。

create table #frs (
    is_hidden bit not null,
    column_ordinal int not null,
    name sysname null,
    is_nullable bit not null,
    system_type_id int not null,
    system_type_name nvarchar(256) null,
    max_length smallint not null,
    precision tinyint not null,
    scale tinyint not null,
    collation_name sysname null,
    user_type_id int null,
    user_type_database sysname null,
    user_type_schema sysname null,
    user_type_name sysname null,
    assembly_qualified_type_name nvarchar(4000),
    xml_collection_id int null,
    xml_collection_database sysname null,
    xml_collection_schema sysname null,
    xml_collection_name sysname null,
    is_xml_document bit not null,
    is_case_sensitive bit not null,
    is_fixed_length_clr_type bit not null,
    source_server sysname null,
    source_database sysname null,
    source_schema sysname null,
    source_table sysname null,
    source_column sysname null,
    is_identity_column bit null,
    is_part_of_unique_key bit null,
    is_updateable bit null,
    is_computed_column bit null,
    is_sparse_column_set bit null,
    ordinal_in_order_by_list smallint null,
    order_by_list_length smallint null,
    order_by_is_descending smallint null,
    tds_type_id int not null,
    tds_length int not null,
    tds_collation_id int null,
    tds_collation_sort_id tinyint null
);

テーブルを作成するとき、そのテーブルにクエリのスキーマを格納できます。

declare @tsql nvarchar(max) = 'select top 0 * from sys.credentials';

insert #frs
exec sys.sp_describe_first_result_set @tsql;

select * from #frs;

問題の例

以下の例では、すべて 2 つのテーブルを使用します。 次のステートメントを実行して、これらのテーブルを作成します。

CREATE TABLE dbo.t1 (a int NULL, b varchar(10) NULL, c nvarchar(10) NULL);  
CREATE TABLE dbo.t2 (a smallint NOT NULL, d varchar(20) NOT NULL, e int NOT NULL);  

列の数の違いによるエラー

この例では、可能性のある最初の結果セットの列の数が異なります。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT a FROM t1;  
ELSE  
    SELECT a, b FROM t1;  
SELECT * FROM t; -- Ignored, not a possible first result set.'  
  

データ型の違いによるエラー

考えられる最初の結果セットの間で、列の型が異なります。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT a FROM t1;  
ELSE  
    SELECT a FROM t2;  

結果: エラー、型の不一致 (intsmallint)。

列の名前を特定できない

可能性のある最初の結果セット内の列で、同じ可変長型の長さ、NULL 値の許容、列の名前が異なります。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT d FROM t2; '  

結果: <不明な列名>varchar(20) NULL

別名を使用して列の名前を強制的に同一にする

前の例と同じですが、列の別名を使用して列名を同じにしています。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT d AS b FROM t2;'  

結果: b varchar(20)NULL

列の型を一致できないことによるエラー

可能性のある複数の最初の結果セットの間で、列の型が異なります。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT c FROM t1;'  

結果: エラー、型の不一致 (varchar(10)nvarchar(10))。

結果セットがエラーを返す可能性がある

最初の結果セットはエラーまたは結果セットです。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    RAISERROR(''Some Error'', 16, 1);  
  
ELSE  
    SELECT a FROM t1;  
SELECT e FROM t2; -- Ignored, not a possible first result set.;'  

結果: a intNULL

一部のコード パスが結果を返さない

最初の結果セットが null または結果セットです。

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    RETURN;  
SELECT a FROM t1;'  

結果: a intNULL

動的 SQL からの結果

最初の結果セットは、リテラル文字列であるために検出可能な動的 SQL です。

sp_describe_first_result_set @tsql =   
N'EXEC(N''SELECT a FROM t1'');'  

結果: a INT NULL

動的 SQL からの結果の失敗

動的 SQL のため、最初の結果セットが未定義となります。

sp_describe_first_result_set @tsql =   
N'  
DECLARE @SQL NVARCHAR(max);  
SET @SQL = N''SELECT a FROM t1 WHERE 1 = 1 '';  
IF(1=1)  
    SET @SQL += N'' AND e > 10 '';  
EXEC(@SQL); '  

結果: エラー。 動的 SQL のため、結果は検出できません。

ユーザー指定の結果セット

最初の結果セットがユーザーにより手動で指定されています。

sp_describe_first_result_set @tsql =   
N'  
DECLARE @SQL NVARCHAR(max);  
SET @SQL = N''SELECT a FROM t1 WHERE 1 = 1 '';  
IF(1=1)  
    SET @SQL += N'' AND e > 10 '';  
EXEC(@SQL)  
    WITH RESULT SETS(  
        (Column1 BIGINT NOT NULL)  
    ); '  

結果: Column1 bigint NOT NULL

あいまいな結果セットによって発生するエラー

この例では、user1 という名前の別のユーザーの既定のスキーマ s1 には列 (int NOT NULL) を含む t1 という名前のテーブルがあるものとします。

sp_describe_first_result_set @tsql =   
N'  
    IF(@p > 0)  
    EXECUTE AS USER = ''user1'';  
    SELECT * FROM t1;'  
, @params = N'@p int'  

結果: エラー。 t1 は dbo.t1 または s1.t1 のいずれかで、それぞれ列の数が異なる可能性があります。

結果セットがあいまいな場合でも得られる結果

前の例と同じ想定を使います。

sp_describe_first_result_set @tsql =   
N'  
    IF(@p > 0)  
    EXECUTE AS USER = ''user1'';  
    SELECT a FROM t1;'  

結果: a int NULL。dbo.t1.a と s1.t1.a はどちらも int 型で、NULL 値の許容が異なるため。

参照

sp_describe_undeclared_parameters (Transact-SQL)
sys.dm_exec_describe_first_result_set (Transact-SQL)
sys.dm_exec_describe_first_result_set_for_object (Transact-SQL)