表值参数作为存储过程的输出参数


33

可以将表值参数用作存储过程的输出参数吗?

这是我想用代码做的

/*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

Answers:



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)

接下来,创建第二个存储过程,该存储过程将接受表值参数。

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

除了remus很好的回答,包括他提供的链接

如何在存储过程之间共享数据

在某些情况下,将存储过程的结果保存到表中时会出现以下错误消息:

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)

之后,您将在屏幕上获得所需的信息,或者如果您已将临时表作为参数传递,它将立即具有数据。

这是我找到的一种解决方案,但是我只能将其用于自己的工作,DBA否则将被认为是Sql Injection的高风险。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.