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:

  1. A mesa #new_temporary_table está sendo criada no âmbito da chamada para exec sp_executesql que é diferente daquele do meu processo armazenado.Esta é a razão pela qual o próximo exec 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-4fee8880d18a

  2. Eu 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 outro

  3. Neste 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.

Foi útil?

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:

http://connect.microsoft.com/SQLServer/feedback/details/425990/ssms-allow-same-semantics-for-xml-docs-as-query-windows

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top