[以前にこの質問に答えたことがあることに気づきました]
ストアドプロシージャに対してこれを行うことは、ビューやテーブルの場合よりもはるかに複雑です。問題の1つは、ストアドプロシージャが、入力パラメータや、サーバーの状態や時刻など、制御できないものに応じて、複数の異なるコードパスを持つ可能性があることです。たとえば、このストアドプロシージャ?条件に関係なく複数の結果セットがある場合はどうなりますか?
CREATE PROCEDURE dbo.foo
@bar INT
AS
BEGIN
SET NOCOUNT ON;
IF @bar = 1
SELECT a, b, c FROM dbo.blat;
ELSE
SELECT d, e, f, g, h FROM dbo.splunge;
END
GO
ストアドプロシージャにコードパスがなく、常に同じ結果セットが表示されると確信している場合(および、ストアドプロシージャにオプション以外のパラメータがある場合に提供する値を事前に決定できる場合)、簡単な例を見てみましょう。
CREATE PROCEDURE dbo.bar
AS
BEGIN
SET NOCOUNT ON;
SELECT a = 'a', b = 1, c = GETDATE();
END
GO
FMTONLY
1つの方法は、次のようなことを行うことです。
SET FMTONLY ON;
GO
EXEC dbo.bar;
これにより、空の結果セットが提供され、クライアントアプリケーションはその結果セットのプロパティを調べて、列名とデータ型を判別できます。
現在、SET FMTONLY ON;
には多くの問題があります。 ここでは説明しませんが、少なくとも、このコマンドは非推奨になっていることに注意してください。これには正当な理由があります。また、SET FMTONLY OFF;
にも注意してください。 完了したら、またはストアドプロシージャを正常に作成したのに、実行できないのはなぜか疑問に思うでしょう。いいえ、それは私に起こったばかりなので、私はあなたにそれについて警告していません。本音。 :-)
OPENQUERY
ループバックリンクサーバーを作成することで、OPENQUERY
などのツールを使用できます。 ストアドプロシージャを実行しますが、検査できる構成可能な結果セットを返します(非常に緩い定義として受け入れてください)。最初にループバックサーバーを作成します(これは、FOO
という名前のローカルインスタンスを想定しています。 ):
USE master;
GO
EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server'
GO
EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',
@optvalue=N'true';
これで、上記の手順を実行して、次のようなクエリにフィードできます。
SELECT * INTO #t
FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;')
WHERE 1 = 0;
SELECT c.name, t.name
FROM tempdb.sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
WHERE c.[object_id] = OBJECT_ID('tempdb..#t');
これはエイリアスタイプ(以前はユーザー定義データタイプと呼ばれていました)を無視し、たとえばsysname
として定義された列に2つの行を表示する場合もあります。 。しかし、上記から次のようになります:
name name
---- --------
b int
c datetime
a varchar
明らかに、ここで行うべき作業は他にもあります-varchar
長さは表示されません。datetime2
などの他のタイプの精度/スケールを取得する必要があります 、time
およびdecimal
。しかし、それは始まりです。
SQL Server 2012
SQL Server 2012には、メタデータの検出をはるかに簡単にするいくつかの新機能があります。上記の手順では、次のことができます。
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('dbo.bar'),
NULL
);
とりわけ、これは実際に精度とスケールを提供し、エイリアスタイプを解決します。上記の手順の場合、これにより次のようになります。
name system_type_name
---- ----------------
a varchar(1)
b int
c datetime
視覚的にはそれほど違いはありませんが、さまざまな精度とスケールですべての異なるデータ型を調べ始めると、この関数が追加の作業を行うことに感謝します。
欠点:SQL Server 2012では、少なくともこれらの関数は最初のでのみ機能します。 結果セット(関数の名前が示すように)