背景
我有一个过程,该过程具有来自动态SQL的INSERT INTO ... EXEC (@sql)
。
该过程的结果在过程之外的INSERTed INTO
表中。当我尝试这样做时,我得到一个错误:
[S0001] [8164]不能嵌套INSERT EXEC语句。
在其他问题中讨论了此错误,但针对内部过程的调用而不是动态SQL:
错误示例:
-- =================================
-- table with test data
-- =================================
CREATE TABLE dbo.TestInsertIntoDynamicData1
(
data nvarchar(max)
)
INSERT INTO dbo.TestInsertIntoDynamicData1
VALUES ('one1'), ('two1'), ('three1')
GO
-- =================================
-- another table with test data
-- =================================
CREATE TABLE dbo.TestInsertIntoDynamicData2
(
data nvarchar(max)
)
INSERT INTO dbo.TestInsertIntoDynamicData2
VALUES ('one2'), ('two2'), ('three2')
GO
-- =================================
-- procedure with dynamic query
-- =================================
CREATE PROCEDURE dbo.TestInsertIntoDynamicProc
@TableName nvarchar(100)
AS
BEGIN
DECLARE @Results table(
data nvarchar(max)
)
DECLARE @sql nvarchar(max)
SET @sql = '
SELECT data
FROM dbo.' + @TableName + ';
'
-- FIRST INSERT INTO ... EXEC ...
INSERT INTO @Results -- this INSERT is required for example
EXEC (@sql)
SELECT *
FROM @Results;
END
GO
-- =================================
-- CALL
-- =================================
DECLARE @ResultsOfProc table(
data nvarchar(max)
)
-- SECOND INSERT INTO ... EXEC ...
INSERT INTO @ResultsOfProc (data)
EXEC dbo.TestInsertIntoDynamicProc @TableName = 'TestInsertIntoDynamicData2'
SELECT *
FROM @ResultsOfProc;
GO
DROP TABLE dbo.TestInsertIntoDynamicData1
DROP TABLE dbo.TestInsertIntoDynamicData2
DROP PROCEDURE dbo.TestInsertIntoDynamicProc
https://stackoverflow.com/a/2917775/7573844
问题
我们如何解决这个错误?
答案 0 :(得分:0)
将INSERT INTO
移至动态查询。
将表变量重构为临时表,以便在动态查询中使用它。
固定步骤:
CREATE PROCEDURE dbo.TestInsertIntoDynamicProcFixed
@TableName nvarchar(100)
AS
BEGIN
CREATE TABLE #Results ( -- refactor to temp table
data nvarchar(max)
)
DECLARE @sql nvarchar(max)
SET @sql = '
INSERT INTO #Results -- move INSERT to here
SELECT data
FROM dbo.' + @TableName + ';
'
-- FIRST INSERT INTO ... EXEC ...
EXEC (@sql)
SELECT *
FROM #Results;
END
GO