ストアドプロシージャの出力パラメーターとしてのテーブル値パラメーター


33

ストアドプロシージャの出力パラメーターとして使用されるTable-Valuedパラメーターは可能ですか?

ここに、私がコードでやりたいこと

/*First I create MY type */
CREATE TYPE typ_test AS TABLE 
(
     id int not null
    ,name varchar(50) not null
    ,value varchar(50) not null
    PRIMARY KEY (id)
)
GO


--Now I want to create stored procedu whic is going to send output type I created, 
--But it looks like it is inpossible, at least in SQL2008
create  PROCEDURE [dbo].sp_test
         @od datetime 
        ,@do datetime 
        ,@poruka varchar(Max) output
        ,@iznos money output 
        ,@racun_stavke  dbo.typ_test   READONLY --Can I Change READONLY with OUTPUT ?
AS
BEGIN
    SET NOCOUNT ON;

    /*FILL MY OUTPUT PARAMS AS I LIKE */


    end

回答:



1

これは古い記事ですが、「ストアドプロシージャの出力パラメーターとしてのテーブル値パラメーター」を検索していたとき、トップ近くにありました。テーブル値パラメーターを出力パラメーターとして渡すことはできないことは理解していますが、目標はそのテーブル値出力パラメーターを別の手順でテーブル値入力パラメーターとして使用することだと思います。この作品の作り方の例を紹介します。

まず、使用するデータを作成します。

create table tbl1
(
id int,
fname varchar(10),
gender varchar(10)
);
create table tbl2
(
id int,
lname varchar(10)
);
insert into tbl1
values
(1,'bob'  ,'m'),
(2,'tom'  ,'m'),
(3,'sally','f')
;
insert into tbl2
values
(1,'jones'   ),
(2,'johnson' ),
(3,'smith'   )
;

次に、ストアドプロシージャを作成して、データの一部をキャプチャします。通常、これは、テーブル値の出力パラメーターを作成しようとしている場所です。

create procedure usp_OUTPUT1
 @gender varchar(10)
as
Begin
    select id from tbl1 where gender = @gender
End

さらに、最初のストアドプロシージャからのデータを次のストアドプロシージャの入力パラメータとして渡すことができるデータ型(テーブル型)を作成する必要があります。

create type tblType as Table (id int)

次に、テーブル値パラメーターを受け入れる2番目のストアドプロシージャを作成します。

create procedure usp_OUTPUT2
@tblType tblType readonly  --referencing the type created and specify readonly
as
begin
 select lname from tbl2 where id in (select id from @tblType)
end

確かに、これは真のテーブル値の出力パラメーターではありませんが、探しているものと同様の結果を生成する可能性があります。テーブル値パラメーターを宣言し、ストアドプロシージャを実行してデータを入力し、次のプロシージャの入力変数として使用します。

Declare @tblType tblType 
insert into @tblType execute usp_OUTPUT1 'm'
execute usp_OUTPUT2 @tblType

1

彼が提供したリンクを含むレムスによるきちんと置かれた答えに加えて

ストアドプロシージャ間でデータを共有する方法

ストアドプロシージャの結果をテーブルに保存するときに、次のエラーメッセージが表示される場合があります。

INSERT EXECステートメントはネストできません。

現在のトランザクションはコミットできず、ログファイルに書き込む操作をサポートできません。トランザクションをロールバックする

そして、これが私自身の使用のために開発した自分のストアドプロシージャで発生した場合

たとえば、login所属するすべてのADグループと、サーバー内のすべてのデータベースのすべてのアクセス許可を確認するツール

プロシージャの外部に一時テーブルを作成し、その名前をパラメーターとして渡します

--===============
-- this way below it works, by passing a temp table as a parameter
--===============

                if OBJECT_ID('tempdb.dbo.#my_table') IS NOT NULL
                   DROP TABLE #my_table

                CREATE TABLE #my_table(
                    db nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                   permission_type nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    login_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    role_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    Obj    nvarchar(517)   COLLATE Latin1_General_CI_AS  NULL,
                    Permission nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    script nvarchar(1008)  COLLATE Latin1_General_CI_AS  NULL
                ) 

                exec sp_GetLoginDBPermissionsX 
                    @Login='my_loginname', 
                    @debug=0,
                    @where_to_save ='#my_table'

                select *
                from #my_table

そして、プロシージャ内で、すべての計算の後、最終データを返すとき(例の下)、テーブルに出力するのか、画面に戻すのかを確認し、スクリプトを動的に作成します。

            select @sql = case when @where_to_save IS not null then 
            '
            insert into ' + @where_to_save + '(db,Permission_Type,login_,role_,obj,Permission,script) '
            else '' end + 
'
        SELECT 
            J.db,
            J.Permission_Type,
            J.login_,
            J.role_,
            J.Obj,
            J.Permission,
            J.script
        FROM #tablewithpermissions J
        WHERE J.login_ IN ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
           OR J.role_ IN  ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
       ORDER BY J.DB, J.[permission_order]
'
        --print(@sql)

        EXEC(@SQL)

その後、必要な情報を画面に表示するか、パラメータとして一時テーブルを渡した場合、データを取得します。

これは私が見つけた1つの解決策ですが、私は自分の仕事にのみ使用しDBAます。そうしないと、SQLインジェクションのリスクが高いと見なされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.