46

重複の可能性:
ストアド プロシージャの結果セットの列定義を取得する

次の SQL を使用して、テーブルまたはビューの列名と型を取得します。

DECLARE @viewname varchar (250);

select a.name as colname,b.name as typename 
from syscolumns a, systypes b -- GAH!
where a.id = object_id(@viewname) 
and a.xtype=b.xtype 
and b.name <> 'sysname'

ストアド プロシージャの出力列に対して同様のことを行うにはどうすればよいですか?

4

2 に答える 2

104

[以前この質問に回答したことがあることに気づきました]

ストアド プロシージャに対してこれを行うのは、ビューやテーブルの場合よりもはるかに複雑です。問題の 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. しかし、上記から次のようになります。

name   name
----   --------
b      int
c      datetime
a      varchar

明らかに、ここで行う作業は他にもあります。長さは表示されません。また、やvarcharなどの他の型の精度/スケールを取得する必要があります。しかし、それは始まりです。datetime2timedecimal

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 では、少なくともこれらの関数は最初の結果セットに対してのみ機能します(関数の名前が示すように)。

于 2013-01-29T03:18:56.540 に答える
2

すべてのストアド プロシージャとそのすべてのパラメーターを返そうとしていますか? このようなものがそのために機能するはずです。

select * from information_schema.parameters

ストアド プロシージャから返された列を取得する必要がある場合は、次を参照してください。

ストアド プロシージャから返された列名/型を取得する

于 2013-01-29T02:53:10.723 に答える