além da resposta bem feita por remus, incluindo o link que ele forneceu
Como compartilhar dados entre procedimentos armazenados
há situações em que você recebe as seguintes mensagens de erro ao salvar os resultados de um procedimento armazenado em uma tabela:
Uma instrução INSERT EXEC não pode ser aninhada.
A transação atual não pode ser confirmada e não pode suportar operações que gravam no arquivo de log. Reverter a transação
e quando isso acontece nos meus próprios procedimentos armazenados que desenvolvo para meu próprio uso
por exemplo, uma ferramenta para me informar sobre login
todos os grupos do AD aos quais pertence e todas as suas permissões em todos os bancos de dados em um servidor
Crio uma tabela temporária fora do procedimento e passo seu nome como parâmetro
--===============
-- this way below it works, by passing a temp table as a parameter
--===============
if OBJECT_ID('tempdb.dbo.#my_table') IS NOT NULL
DROP TABLE #my_table
CREATE TABLE #my_table(
db nvarchar(128) COLLATE Latin1_General_CI_AS NULL,
permission_type nvarchar(128) COLLATE Latin1_General_CI_AS NULL,
login_ nvarchar(128) COLLATE Latin1_General_CI_AS NULL,
role_ nvarchar(128) COLLATE Latin1_General_CI_AS NULL,
Obj nvarchar(517) COLLATE Latin1_General_CI_AS NULL,
Permission nvarchar(128) COLLATE Latin1_General_CI_AS NULL,
script nvarchar(1008) COLLATE Latin1_General_CI_AS NULL
)
exec sp_GetLoginDBPermissionsX
@Login='my_loginname',
@debug=0,
@where_to_save ='#my_table'
select *
from #my_table
e dentro do procedimento, depois de todos os cálculos, quando estou retornando os dados finais (abaixo de um exemplo), verifico se estamos produzindo para uma tabela ou apenas voltando para a tela e crio o script dinamicamente.
select @sql = case when @where_to_save IS not null then
'
insert into ' + @where_to_save + '(db,Permission_Type,login_,role_,obj,Permission,script) '
else '' end +
'
SELECT
J.db,
J.Permission_Type,
J.login_,
J.role_,
J.Obj,
J.Permission,
J.script
FROM #tablewithpermissions J
WHERE J.login_ IN ( SELECT L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
OR J.role_ IN ( SELECT L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
ORDER BY J.DB, J.[permission_order]
'
--print(@sql)
EXEC(@SQL)
Depois disso, você terá as informações necessárias na tela ou se tiver passado uma tabela temporária como parâmetro, eles terão os dados agora.
essa é uma solução que encontrei, mas a uso apenas para meus próprios trabalhos, DBA
caso contrário, isso será considerado de alto risco para a injeção de sql .