有两个存储过程-p1
和p2
。 p1
更改数据库,并从表类型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
构造。
答案 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实例的所有连接。
更新-可用性:
在存储过程中创建的本地临时表已删除 存储过程完成后自动执行。该表可以是 由存储执行的任何嵌套存储过程引用 创建表的过程。该表不能被 调用创建表的存储过程的过程。
因此,在我们的案例中,sp_2
是外部存储过程,而sp_1是嵌套存储过程。