web-dev-qa-db-ja.com

ストアドプロシージャの入力値と出力値を決定する方法

私は何百ものSPを持っています。知りたいのですが。

  • タイプの入力パラメータ
  • タイプを持つ出力フィールド(出力パラメーターではない)

もちろん、それぞれを手動で調べて書き留めることもできますが、その中での楽しみはどこにありますか...いいえ、文字通りISその中での楽しみ:)

これは可能ですか、それともSql Management Studio 2008 R2にはすでにこの機能がありますか?

私はどこから始めればよいのかさえわからないので、どんな答えでも受け入れられます。

質問の強化のために編集します。2つの異なるタスクと見なすと、これを簡単に達成できますか?クライアント側でリフレクションを使用する場合でも。 (速くて汚いコンソールアプリで十分でしょう。)

7
Michael Wells

システムビュー INFORMATION_SCHEMA.PARAMETERS を使用してそれを実行できるはずです。必要なものがそこにあります。

「現在のデータベースで現在のユーザーがアクセスできるユーザー定義関数またはストアドプロシージャのパラメーターごとに1行を返します。関数の場合、このビューは戻り値情報を含む1行も返します。」

PS:マーティンの質問への答えが「結果セットの列」である場合、私の答えは無視してください。これは、プロシージャのパラメーターのみであり、結果ではありません。

4
Marian

入力パラメータと出力パラメータについては、 sys.parameterssys.procedures および sys.types を確認できます。以下は、さまざまな入力/出力パラメーター、エイリアスタイプ、さらにTVP(2008+のみ)を使用した手順です。

USE [tempdb];
GO

CREATE TYPE dbo.TVPType AS TABLE(id INT);
GO

CREATE PROCEDURE dbo.foobar
    @a INT,
    @b SYSNAME = N'foo',
    @c DATETIME = NULL,
    @d dbo.TVPType READONLY,
    @e NVARCHAR(MAX),
    @f INT OUTPUT,
    @g INT = NULL OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT @f = COUNT(*) FROM sys.objects;
END
GO

そして、これがsys.parameterssys.proceduresおよびsys.typesからこの情報を取得するクエリです。

SELECT 
    s = QUOTENAME(OBJECT_SCHEMA_NAME(p.[object_id])),
    o = QUOTENAME(p.name),
    p = pr.name, 
    t1.name,
    pr.max_length, 
    pr.[precision], 
    pr.scale, 
    pr.is_output,
    pr.is_readonly
FROM sys.procedures AS p
INNER JOIN sys.parameters AS pr
ON p.[object_id] = pr.[object_id]
LEFT OUTER JOIN sys.types AS t1 
ON (pr.system_type_id = t1.system_type_id)
AND (pr.system_type_id <> t1.system_type_id
OR pr.user_type_id = t1.user_type_id)
WHERE p.[object_id] = OBJECT_ID('dbo.foobar')
ORDER BY pr.parameter_id;

結果:

s       o           p   name    max_length  [precision]  scale  is_output  is_readonly
-----   ----------  --- -------- ---------  -----------  -----  ---------  -----------
[dbo]   [foobar]    @a  int              4           10      0          0            0
[dbo]   [foobar]    @b  sysname        256            0      0          0            0
[dbo]   [foobar]    @c  datetime         8           23      3          0            0
[dbo]   [foobar]    @d  TVPType         -1            0      0          0            1
[dbo]   [foobar]    @e  nvarchar        -1            0      0          0            0
[dbo]   [foobar]    @f  int              4           10      0          1            0
[dbo]   [foobar]    @g  int              4           10      0          1            0

明らかに、これらの値を実際のデータ型のように見せるには、マッサージを行う必要があります。たとえば-1でない限り、nvarcharのmax_lengthを半分にカットします。-1の場合、MAXと交換する必要があります。 10進数、数値などの場合は、精度とスケールを適切に追加します。 TVPを使用している場合は、それらのタイプにSCHEMA_NAMEを使用してスキーマを取得する必要があるでしょう。など.

残念ながら、パラメータがnull可能かどうか、またはデフォルト値があるかどうか、およびデフォルト値が何であるかを判断するために、ブルートフォースがプロシージャ本体を解析する(そして、それも深刻な忍者RegExスキルなしでは簡単ではない)以外に方法はありません。この情報はメタデータに保存されないだけです。has_default_valueにはdefault_valuesys.parametersの列がありますが、CLRの場合、これらは非NULLまたはゼロではありません手順。 2006年以降、これについて不満を言っています ですが、この分野での進展はまだ見られていません(ただし、このConnectアイテムの回避策は投稿しましたが、いくつかの原因になるため、ここでは再現しません)ストアドプロシージャのコーディングスタイルに関する不当な仮定)。また、パラメーターがオプションかどうかを判断する希望さえもありません(上記の@cおよび@gなど)。

結果セットについては、Martinは正解です。 SET FMTONLY ON を使用する以外に、結果が何で構成されるかを理解するための確実な方法はありません。これにはいくつかの特異なバグがあるので、私はそれを避けます。よく使われる方法は、「ループバック」で OPENQUERY を使用することです リンクサーバー 、結果を#tempテーブルに選択しますが、これはプロシージャ結果セットは1つだけです。マーティンの以前の回答の1つに良い例があります。

SQL Serverで、ストアドプロシージャの結果を保持できる一時テーブルを作成する最も簡単な方法は何ですか?

出力を#tempテーブルに配置したら、次を実行できます。

EXEC tempdb..sp_help '#tablename';

これは、とりわけ、列名とそのデータ型のリストを出力します。これは何百ものストアドプロシージャを実行するための退屈なプロセスになりますが、自動化の方法についてはアイデアを持っているので、これが興味深い解決策であると思われる場合はお知らせください。私の答えを広げることができます。

Martinはこれをlot簡単にするSQL Server 2012の新機能についても言及しました(ただし、ストアドプロシージャの最初の結果セットに限定されます) 。詳細については、上記の同じ質問に対する私の回答で確認できます。

戻り値については、メタデータから取得する方法がわかりません。

3
Aaron Bertrand