Eu tenho um procedimento armazenado que retorna 80 colunas e 300 linhas. Eu quero escrever um select que recebe 2 dessas colunas. Algo como
SELECT col1, col2 FROM EXEC MyStoredProc 'param1', 'param2'
Quando usei a sintaxe acima, recebo o erro:
"Nome da coluna inválido".
Eu sei que a solução mais fácil seria alterar o procedimento armazenado, mas não o escrevi e não posso alterá-lo.
Existe alguma maneira de fazer o que eu quero?
Eu poderia criar uma tabela temporária para colocar os resultados, mas como existem 80 colunas, seria necessário criar uma tabela temporária de 80 colunas apenas para obter 2 colunas. Eu queria evitar rastrear todas as colunas retornadas.
Tentei usar
WITH SprocResults AS ....
como sugerido por Mark, mas obtive 2 errosSintaxe incorreta perto da palavra-chave 'EXEC'.
Sintaxe incorreta perto de ')'.Tentei declarar uma variável de tabela e recebi o seguinte erro
Erro de inserção: o nome da coluna ou o número de valores fornecidos não corresponde à definição da tabela
Se eu tentar
SELECT * FROM EXEC MyStoredProc 'param1', 'param2'
, recebo o erro:Sintaxe incorreta perto da palavra-chave 'exec'.
fonte
EXEC
não é uma palavra-chave do MySQL (o equivalente do MySQL é instruções preparadas ). Embora eu gostaria de saber a resposta para o MySQL, as respostas abaixo são direcionadas ao T-SQL. Marcando novamente.Respostas:
Você pode dividir a consulta? Insira os resultados do processo armazenados em uma variável de tabela ou em uma tabela temporária. Em seguida, selecione as 2 colunas da variável da tabela.
fonte
Aqui está um link para um documento muito bom, explicando todas as maneiras diferentes de resolver seu problema (embora muitas delas não possam ser usadas, pois você não pode modificar o procedimento armazenado existente).
Como compartilhar dados entre procedimentos armazenados
A resposta do Gulzar funcionará (está documentada no link acima), mas será um incômodo escrever (você precisará especificar todos os 80 nomes de coluna na sua declaração @tablevar (col1, ...). se uma coluna for adicionada ao esquema ou a saída for alterada, ela precisará ser atualizada no seu código ou ocorrerá um erro.
fonte
Fonte:
http://stevesmithblog.com/blog/select-from-a-stored-procedure/
fonte
Isso funciona para mim: (ou seja, eu só preciso de 2 colunas das mais de 30 retornadas por
sp_help_job
)Antes que isso funcionasse, eu precisava executar o seguinte:
.... para atualizar a
sys.servers
tabela. (por exemplo, o uso de uma referência própria no OPENQUERY parece estar desativado por padrão.)Por minha simples exigência, não encontrei nenhum dos problemas descritos na seção OPENQUERY do excelente link de Lance.
Rossini, se você precisar definir dinamicamente esses parâmetros de entrada, o uso do OPENQUERY se tornará um pouco mais complicado:
Não tenho certeza das diferenças (se houver) entre usar
sp_serveroption
para atualizarsys.servers
diretamente a auto-referência existente e usarsp_addlinkedserver
(como descrito no link de Lance) para criar um duplicado / alias.Nota 1: Prefiro OPENQUERY sobre OPENROWSET, pois o OPENQUERY não requer a definição da cadeia de conexão no proc.
Nota 2: Tendo dito tudo isso: normalmente eu usaria INSERT ... EXEC :) Sim, são 10 minutos de digitação extra, mas se eu puder ajudá-lo, prefiro não brincar com:
(a) aspas entre aspas dentro cotações e
(b) tabelas sys e / ou configurações de servidor vinculado autorreferenciosamente sorrateiras (ou seja, para essas, preciso defender meu caso com nossos DBAs todo-poderosos):
No entanto, neste caso, eu não poderia usar uma construção INSERT ... EXEC, como
sp_help_job
já está usando uma. ("Uma instrução INSERT EXEC não pode ser aninhada.")fonte
Para conseguir isso, primeiro crie um
#test_table
like abaixo:Agora execute o procedimento e coloque valor em
#test_table
:Agora você busca o valor de
#test_table
:fonte
Se você conseguir modificar o procedimento armazenado, poderá colocar facilmente as definições de colunas necessárias como parâmetro e usar uma tabela temporária criada automaticamente:
Nesse caso, você não precisa criar uma tabela temporária manualmente - ela é criada automaticamente. Espero que isto ajude.
fonte
Pode ser útil saber por que isso é tão difícil. Um procedimento armazenado pode retornar apenas texto (imprimir 'texto') ou retornar várias tabelas ou retornar nenhuma tabela.
Então, algo como
SELECT * FROM (exec sp_tables) Table1
não vai funcionarfonte
(Assumindo o SQL Server)
A única maneira de trabalhar com os resultados de um procedimento armazenado no T-SQL é usar a
INSERT INTO ... EXEC
sintaxe. Isso oferece a opção de inserir em uma tabela temporária ou variável de tabela e, a partir daí, selecionar os dados necessários.fonte
Um hack rápido seria adicionar um novo parâmetro
'@Column_Name'
e fazer com que a função de chamada defina o nome da coluna a ser recuperada. Na parte de retorno do seu sproc, você teria instruções if / else e retornaria apenas a coluna especificada ou, se vazia - retornaria tudo.fonte
Se você estiver fazendo isso para validação manual dos dados, poderá fazê-lo com o LINQPad.
Crie uma conexão com o banco de dados no LinqPad e crie instruções C # semelhantes à seguinte:
Referência http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx
fonte
Para o SQL Server, acho que isso funciona bem:
Crie uma tabela temporária (ou tabela permanente, realmente não importa) e insira uma instrução no procedimento armazenado. O conjunto de resultados do SP deve corresponder às colunas da sua tabela, caso contrário, você receberá um erro.
Aqui está um exemplo:
É isso aí!
fonte
Como foi mencionado na pergunta, é difícil definir a tabela temporária de 80 colunas antes de executar o procedimento armazenado.
Portanto, o contrário é preencher a tabela com base no conjunto de resultados do procedimento armazenado.
Se você estiver recebendo algum erro, precisará ativar as consultas distribuídas ad hoc executando a consulta a seguir.
Para executar
sp_configure
com os dois parâmetros para alterar uma opção de configuração ou executar aRECONFIGURE
instrução, você deve receber aALTER SETTINGS
permissão no nível do servidorAgora você pode selecionar suas colunas específicas na tabela gerada
fonte
tente isso
fonte
Eu sei que executar a partir de sp e inserir na tabela temporária ou variável de tabela seria uma opção, mas não acho que esse seja seu requisito. Conforme sua exigência, esta instrução de consulta abaixo deve funcionar:
Se você possui uma conexão confiável, use esta instrução de consulta abaixo:
se você estiver recebendo um erro ao executar a instrução acima, basta executar esta instrução abaixo:
Espero que isso ajude alguém que enfrentou esse tipo de problema semelhante. Se alguém tentar com a tabela temporária ou variável de tabela que deve ser assim abaixo, mas nesse cenário você deve saber quantas colunas seu sp está retornando, então você deve criar tantas colunas na tabela temp ou na variável de tabela:
fonte
Para quem possui o SQL 2012 ou posterior, consegui fazer isso com procedimentos armazenados que não são dinâmicos e têm as mesmas colunas sempre.
A idéia geral é criar a consulta dinâmica para criar, inserir, selecionar e soltar a tabela temporária e executá-la depois de gerada. Giro dinamicamente a tabela temporária, primeiro recuperando nomes e tipos de colunas do procedimento armazenado .
Nota: existem soluções muito melhores e mais universais que funcionarão com menos linhas de código se você estiver disposto / apto a atualizar o SP ou alterar a configuração e o uso
OPENROWSET
. Use o abaixo se você não tiver outra maneira.fonte
A maneira mais fácil de fazer, se você precisar fazer isso apenas uma vez:
Exporte para o Excel no assistente Importar e Exportar e, em seguida, importe esse excel para uma tabela.
fonte
Crie uma visão dinâmica e obtenha resultados dela .......
fonte
Recortaria e colaria o SP original e excluiria todas as colunas, exceto as 2 desejadas. Ou. Eu traria o conjunto de resultados de volta, mapeá-lo para um objeto de negócios adequado e, em seguida, LINQ fora das duas colunas.
fonte