Eu tenho um proc armazenado spGetSites que retorna três colunas para SiteName, SiteId e UnitCount. O proc armazenado funciona perfeitamente bem. Estou tentando armazenar os resultados do procedimento armazenado em uma tabela temporária @Site para usar em meu relatório com a sintaxe abaixo. Desta vez, recebi uma mensagem de erro: “Instrução INSERT EXEC não pode ser aninhada”

Não posso usar as instruções INSERT e EXEC ao mesmo tempo?

DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0 

Comentários

  • Você deve , dbfiddle.uk/… Adicione seu procedimento armazenado à pergunta e marque sua versão do SQL Server.

Resposta

Se você olhar o código do seu spGetSites procedimento, em algum lugar nesse procedimento está outro INSERT...EXEC. Pode ser diretamente nesse procedimento, ou aninhado nas entranhas de algum outro procedimento que ele chama.

Em última análise, se um procedimento armazenado usar INSERT...EXEC, se você tentar chamar esse procedimento armazenado no contexto de outro INSERT...EXEC, você obterá o erro que está vendo .

Como você corrige?

  1. Você poderia simplesmente pegar o INSERT...EXEC interno e embutir o código para isso procedimento armazenado único. Porém, eu suspeito que outro procedimento pode estar lá por um motivo: ou seja, para manter seu código SECO.

  2. Uma vez que este é um Get procedimento, esperançosamente não há manipulação de dados acontecendo em qualquer lugar na pilha de chamadas. Você poderia converter o procedimento filho em uma função com valor de tabela. Isso permitiria a você converter aquele INSERT...EXEC interno em um INSERT...SELECT e resolva esse problema.

  3. Use tabelas temporárias com escopo para o procedimento externo para passar dados entre os procedimentos. Esta solução obtém complicado, por isso não é o meu favorito e geralmente desencorajo esse padrão quando há uma opção melhor – mas por uma questão de integridade, vou incluí-lo aqui. Basicamente, se você criar sua tabela #temp fora de spGetSites, poderá usá-la dentro de spGetSites (sem criá-la lá dentro) e da tabela com os dados inseridos sobreviverá à execução do procedimento e continuará a funcionar.

Não gosto da opção 3 porque é um padrão de codificação complexo o suficiente para garantir que alguém bagunce tudo no futuro, a menos que todos estejam a bordo e familiarizados com a codificação padrão: * spGetSites falhará a menos que você crie a tabela primeiro. Todos os chamadores precisam se lembrar de criar a tabela exatamente da mesma primeiro. * spGetSites não pode “presumir que a tabela está vazia. Ela pode ter dados existentes da chamada externa (ou uma execução anterior do mesmo chamador) * Solução de problemas e depuração (e até mesmo obter um plano de consulta) para spGetSites é mais complexo por causa da confusão na criação da tabela.

O que eu faria?

Sem saber o quão complexo o o código está por trás de spGetSites, eu “daria uma olhada na criação de um TVF embutido que substitua o INSERT...EXEC interno por INSERT...SELECT ou possivelmente todo o spGetSites poderia ser simplificado / reescrito para torná-lo autocontido sem o INSERT...EXEC

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *