避免 "An INSERT EXEC statement cannot be nested"
Avoiding "An INSERT EXEC statement cannot be nested"
我知道这不可能嵌套 insert ... exec
语句,但我仍然很感兴趣 - 有没有办法检查我是否已经有活动的 insert ... exec
以避免实际错误?
所以我想要这样的东西:
....
if <check if I have outer insert into exec> = 0
insert into <#some temporary table>
exec <stored procedure>
换句话说 - insert ... exec
是可选的,拥有它很好,但如果有人试图用外部 insert ... exec
调用我的过程,我想跳过它
如所述here
This is a common issue when attempting to 'bubble' up data from a
chain of stored procedures. A restriction in SQL Server is you can
only have one INSERT-EXEC active at a time. I recommend looking at
How to Share Data Between Stored Procedures which is a very
thorough article on patterns to work around this type of problem.
试试 OpenRowset
INSERT INTO #YOUR_TEMP_TABLE
SELECT * FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off EXEC [ServerName].dbo.[StoredProcedureName] 1,2,3')
一种天真的方法是使用 TRY/CATCH
块:
BEGIN
DECLARE @isNested BIT = 0;
BEGIN TRY
BEGIN TRANSACTION;
EXEC p2;
ROLLBACK; --COMMIT;
END TRY
BEGIN CATCH
-- Msg 8164 An INSERT EXEC statement cannot be nested.
IF ERROR_NUMBER() = 8164 SET @isNested = 1;
ROLLBACK;
END CATCH
SELECT @isNested;
END
我正在使用 OBJECT_ID 检查内部过程中是否存在临时 table 以确保我们没有嵌套插入执行场景。
当我们检查 table 不存在时,我们创建 table 并插入到 table 中。
我在下面提供了示例代码供您参考。
--Procedure for INSERT...EXEC
CREATE PROCEDURE ValuesGetForInsert
AS
BEGIN
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3;
END
GO
--Outer Insert Procedure
CREATE PROCEDURE dbo.OuterInsert
AS
BEGIN
IF OBJECT_ID('tempdb..#Table1') IS NULL
BEGIN
CREATE TABLE #Table1(a int);
INSERT INTO #Table1(a)
EXECUTE ValuesGetForInsert;
END
EXECUTE InnerInsert;
SELECT 'OuterInsert',* FROM #Table1;
END
GO
--Inner Insert Procedure
CREATE PROCEDURE dbo.InnerInsert
AS
BEGIN
IF OBJECT_ID('tempdb..#Table1') IS NULL
BEGIN
CREATE TABLE #Table1(a int);
INSERT INTO #Table1(a)
EXECUTE ValuesGetForInsert;
END
SELECT 'Inner Insert', * FROM #Table1
END
GO
--Executing outer insert or inner insert indepenently
EXECUTE dbo.OuterInsert;
EXECUTE dbo.InnerInsert;
GO
我知道这不可能嵌套 insert ... exec
语句,但我仍然很感兴趣 - 有没有办法检查我是否已经有活动的 insert ... exec
以避免实际错误?
所以我想要这样的东西:
....
if <check if I have outer insert into exec> = 0
insert into <#some temporary table>
exec <stored procedure>
换句话说 - insert ... exec
是可选的,拥有它很好,但如果有人试图用外部 insert ... exec
如所述here
This is a common issue when attempting to 'bubble' up data from a chain of stored procedures. A restriction in SQL Server is you can only have one INSERT-EXEC active at a time. I recommend looking at How to Share Data Between Stored Procedures which is a very thorough article on patterns to work around this type of problem.
试试 OpenRowset
INSERT INTO #YOUR_TEMP_TABLE
SELECT * FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;','set fmtonly off EXEC [ServerName].dbo.[StoredProcedureName] 1,2,3')
一种天真的方法是使用 TRY/CATCH
块:
BEGIN
DECLARE @isNested BIT = 0;
BEGIN TRY
BEGIN TRANSACTION;
EXEC p2;
ROLLBACK; --COMMIT;
END TRY
BEGIN CATCH
-- Msg 8164 An INSERT EXEC statement cannot be nested.
IF ERROR_NUMBER() = 8164 SET @isNested = 1;
ROLLBACK;
END CATCH
SELECT @isNested;
END
我正在使用 OBJECT_ID 检查内部过程中是否存在临时 table 以确保我们没有嵌套插入执行场景。
当我们检查 table 不存在时,我们创建 table 并插入到 table 中。
我在下面提供了示例代码供您参考。
--Procedure for INSERT...EXEC
CREATE PROCEDURE ValuesGetForInsert
AS
BEGIN
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3;
END
GO
--Outer Insert Procedure
CREATE PROCEDURE dbo.OuterInsert
AS
BEGIN
IF OBJECT_ID('tempdb..#Table1') IS NULL
BEGIN
CREATE TABLE #Table1(a int);
INSERT INTO #Table1(a)
EXECUTE ValuesGetForInsert;
END
EXECUTE InnerInsert;
SELECT 'OuterInsert',* FROM #Table1;
END
GO
--Inner Insert Procedure
CREATE PROCEDURE dbo.InnerInsert
AS
BEGIN
IF OBJECT_ID('tempdb..#Table1') IS NULL
BEGIN
CREATE TABLE #Table1(a int);
INSERT INTO #Table1(a)
EXECUTE ValuesGetForInsert;
END
SELECT 'Inner Insert', * FROM #Table1
END
GO
--Executing outer insert or inner insert indepenently
EXECUTE dbo.OuterInsert;
EXECUTE dbo.InnerInsert;
GO