Это проблема с INSERT EXEC
Я сталкивался с этим много раз за эти годы. Вот несколько вариантов - ни один из них не идеален, у каждого есть свои плюсы и минусы, но, тем не менее, он поможет вам преодолеть конечную линию sh.
Образцы процедур:
USE tempdb
GO
-- Sample Procs
CREATE PROC dbo.proc1 @a INT, @b INT
AS
SELECT x.a, x.b
FROM (VALUES(@a,@b)) AS x(a,b)
CROSS JOIN (VALUES(1),(2),(3)) AS xx(x);
GO
CREATE PROC dbo.proc2 @a INT, @b INT
AS
DECLARE @x TABLE (a INT, b INT);
INSERT @x(a,b)
EXEC dbo.proc1 5,10;
SELECT x.a, x.b FROM @x AS x;
Эта ошибка завершится из-за вложенности INSERT EXE C:
DECLARE @a INT = 2, @b INT = 4;
DECLARE @t2 TABLE (a INT, b INT);
INSERT @t2(a,b)
EXEC dbo.proc2 5,10;
Option # 1. Извлеките хранимую процедуру logi c и запустите ее напрямую
Здесь я просто беру logi c из dbo.proc2 и запускаю его ad-ho c
DECLARE @t2 TABLE (a INT, b INT);
DECLARE @a INT = 2, @b INT = 4;
INSERT @t2 (a,b)
-- Logic Extracted right out of dbo.proc1:
SELECT x.a, x.b
FROM (VALUES(@a,@b)) AS x(a,b)
CROSS JOIN (VALUES(1),(2),(3)) AS xx(x);
SELECT t2.* FROM @t2 AS t2;
Вариант № 2 - Извлечь pro c logi c и запустить его как Dynami c SQL
DECLARE @t2 TABLE (a INT, b INT);
DECLARE @a INT = 2,
@b INT = 4;
DECLARE @SQL NVARCHAR(4000) = N'
SELECT x.a, x.b
FROM (VALUES(@a,@b)) AS x(a,b)
CROSS JOIN (VALUES(1),(2),(3)) AS xx(x);',
@ParmDefinition NVARCHAR(500) = N'@a INT, @b INT';
INSERT @t2
EXEC sys.sp_executesql @SQL, @ParmDefinition, @a=@a, @b=@b;
SELECT t2.* FROM @t2 AS t2; -- validation
Опция # 3 - вариант # 2 с pro c кодом непосредственно из метаданных
DECLARE @t2 TABLE (a INT, b INT);
DECLARE @a INT = 2,
@b INT = 4;
DECLARE
@SQL NVARCHAR(4000) =
( SELECT SUBSTRING(f.P, CHARINDEX('SELECT',f.P),LEN(f.P))
FROM (VALUES(OBJECT_DEFINITION(OBJECT_ID('proc1')))) AS f(P)),
@ParmDefinition NVARCHAR(500) = N'@a INT, @b INT';
EXEC sys.sp_executesql @SQL, @ParmDefinition, @a=@a, @b=@b;
Недостатком является разбор того, что мне нужно. Я сделал простой пример с логикой c, начинающейся с предложения SELECT, реальный мир не такой добрый. Положительным моментом по сравнению с добавлением logi c вручную является то, что ваш код будет обновлен. Изменения в pro c автоматически меняют логи c (но также могут нарушить код).
Опция № 4: Глобальная временная таблица
Я на самом деле не пробовал, но это должно работать. Вы можете переписать pro c (в моем примере proc2) следующим образом:
ALTER PROC dbo.proc2 @a INT, @b INT, @output BIT = 1
AS
IF OBJECT_ID('tempdb..##x','U') IS NOT NULL DROP TABLE ##x;
CREATE TABLE ##x(a INT, b INT);
INSERT ##x(a,b)
EXEC dbo.proc1 5,10;
IF @output = 1
SELECT x.a, x.b FROM ##x AS x;
GO
Я заполняю глобальную временную таблицу набором результатов, затем добавляю опцию для отображения вывода или нет. Когда @output = 0, набор результатов будет находиться в ## x, на который можно ссылаться следующим образом:
DECLARE @t2 TABLE (a INT, b INT);
EXEC dbo.proc2 5,10,0;
INSERT @t2(a,b)
SELECT * FROM ##x;
SELECT * FROM @t2;