Acesse tabelas temporárias do SQL Server criadas em escopo diferente
-
11-12-2019 - |
Pergunta
Estou escrevendo um procedimento armazenado para SQL Server 2008 no qual preciso extrair informações de um conjunto de tabelas.Não sei de antemão a estrutura dessas tabelas.Existe outra tabela no mesmo banco de dados que informa os nomes e tipos dos campos desta tabela.
Estou fazendo isso:
declare @sql nvarchar(max)
set @sql = 'select ... into #new_temporary_table ...'
exec sp_executesql @sql
Then I iterate doing:
set @sql = 'insert into #another_temporary_table ... select ... from #new_temporary_table'
exec sp_executesql @sql
Depois disso, descarto a tabela temporária.Isso acontece em um loop, então a tabela será criada, preenchida e eliminada várias vezes, cada vez com colunas diferentes.
Isso falha com o erro:
Nome de objeto inválido:#new_temporary_table.
Depois de pesquisar no Google, descobri que:
A mesa
#new_temporary_table
está sendo criada no âmbito da chamada paraexec sp_executesql
que é diferente daquele do meu processo armazenado.Esta é a razão pela qual o próximoexec sp_executesql
não consegue encontrar a mesa.Esta postagem explica isso:http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/1dd6a408-4ac5-4193-9284-4fee8880d18aEu poderia usar tabelas temporárias globais, que são anexadas com
##
.Não posso fazer isso porque vários processos armazenados podem ser executados ao mesmo tempo e afetariam o estado um do outroNeste artigo diz que se eu me encontrar nesta situação devo alterar a estrutura do banco de dados.Esta não é uma opção para mim:http://www.sommarskog.se/dynamic_sql.html
Uma solução alternativa que encontrei foi combinar todos os select into #new_temporary_table..
e todos os insert into ...
scripts em uma declaração gigantesca.Isso funciona bem, mas tem algumas desvantagens.
Se eu imprimir @sql para solucionar problemas, o texto ficará truncado, por exemplo.
Tenho alguma outra opção?Todas as ideias são bem-vindas.
Solução
Acho que é melhor usar um único script.
Você pode alterar quantos caracteres serão impressos em Ferramentas > Opções > Resultados da consulta > SQL Server > Resultados para texto - altere "Número máximo de caracteres..." de 256 para o máximo (8192).
Se for maior que 8192, sim, a impressão é difícil.Mas você pode tentar uma opção diferente neste caso.Em vez de PRINT @sql;
em vez disso, use o seguinte (com resultados na grade):
SELECT sql FROM (SELECT @sql) AS x(sql) FOR XML PATH;
Agora você pode clicar no resultado e ele abrirá uma nova janela de consulta.Bem, é uma janela de arquivo XML e você não pode executá-la ou ver o código de cores e deve ignorar que ela muda, por exemplo. >
para >
para torná-los válidos como dados XML, mas a partir daqui é fácil observar se você estiver apenas tentando observá-los.Você pode copiá-lo e colá-lo em uma janela real do editor de consultas e fazer uma pesquisa e substituir os caracteres autorizados, se desejar.FWIW, pedi que eles transformassem essas janelas XML em janelas de consulta reais, mas isso foi negado:
Outras dicas
Você poderia usar temperatura global tabelas, mas use um ID de contexto (como newid()) como parte do nome da tabela temporária global.
declare @sql varchar(2000)
declare @contextid varchar(50) = convert(varchar(20), convert(bigint, substring(convert(binary(16), newid()), 1, 4)))
set @sql = 'select getdate() as stuff into ##new_temporary_table_' + @contextid
exec (@sql)
#temp tabelas (não globais) estão disponíveis no escopo em que foram criadas e abaixo.Então você poderia fazer algo como...
while (your_condition = 1) begin
set @sql = 'select ... into #temp1 ...from blah
exec sp_do_the_inserts'
exec(@sql)
end
O sp_do_the_inserts pode parecer...
select * into #temp2 from #temp1
....your special logic here....
Isso pressupõe que você crie sp_do_the_inserts antecipadamente, é claro.Não sei se isso atende a sua necessidade.