从另一个存储过程调用存储过程不会产生结果

时间:2019-02-18 12:49:57

标签: sql sql-server

有两个存储过程-p1p2p1更改数据库,并从表类型Table1的表table1_type返回具有某些内容的数据,而p2仅返回p1返回的内容。

CREATE PROCEDURE dbo.p1
  @Resp INT OUTPUT
AS 
/*Change database here*/
SET @Resp = 0;
SELECT * FROM Table1;
GO

CREATE PROCEDURE dbo.p2
  @Resp INT OUTPUT
AS 
DECLARE @tmp table1_type;
INSERT INTO @tmp EXEC dbo.p1 @Resp OUTPUT;
SELECT * FROM @tmp;
GO

如果您下一个请求

DECLARE @tmp dbo.table1_type;
DECLARE @Resp INT;
INSERT INTO @tmp EXEC dbo.p1 @Resp OUTPUT;
SELECT * FROM @tmp;

然后Table1表的内容出现在@tmp表中,并且@Resp变量变为0。但是,如果您调用dbo.p2过程,它将不会返回任何内容(@tmp将为空),变量@Resp也将为空。

DECLARE @tmp dbo.table1_type;
DECLARE @Resp INT;
INSERT INTO @tmp EXEC dbo.p2 @Resp OUTPUT;
SELECT * FROM @tmp;

为什么会发生这种情况?如何调用包含对另一个存储过程的调用的存储过程,以便返回期望的结果?

之所以会这样,是因为您无法在嵌套存储过程中使用INSERT ... EXEC构造。

1 个答案:

答案 0 :(得分:3)

使用OUTPUT只能获得一行。

您可以使用临时表在过程之间共享数据。例如:

CREATE PROCEDURE sp_1 @par1 int,
                          @par2 bit,
                          ... AS
   ...
   INSERT/UPDATE/DELETE #mytemp
GO

CREATE PROCEDURE sp_2 AS
   DECLARE ...
   CREATE TABLE #mytemp (col1 int     NOT NULL,
                         col2 char(5) NULL,
                        ...)
   ...
   EXEC sp_1 @par1, @par2 ...
   SELECT * FROM #mytemp
GO

此外,您还有a great article written by Erland Sommarskog

中所述的许多其他选项

更新-安全:

如果将临时表声明为#tempTable,则这是安全的,因为这些临时表只能由创建的连接访问,并且仅在存储过程执行期间才存在。但是,如果创建一个全局临时表(带有两个符号## tempTable),则这些表是不安全的,因为它们暴露给SQL实例的所有连接。

更新-可用性:

As MSDN says:

  

在存储过程中创建的本地临时表已删除   存储过程完成后自动执行。该表可以是   由存储执行的任何嵌套存储过程引用   创建表的过程。该表不能被   调用创建表的存储过程的过程。

因此,在我们的案例中,sp_2是外部存储过程,而sp_1是嵌套存储过程。