Como chamar um procedimento armazenado para cada linha de uma tabela, onde as colunas de uma linha são parâmetros de entrada para o sp sem usar um Cursor?
sql
sql-server
stored-procedures
cursor
Johannes Rudolph
fonte
fonte
Respostas:
De um modo geral, eu sempre procuro uma abordagem baseada em conjunto (às vezes às custas de alterar o esquema).
No entanto, esse trecho tem seu lugar.
fonte
Você poderia fazer algo assim: ordenar sua tabela, por exemplo, CustomerID (usando a
Sales.Customer
tabela de exemplo AdventureWorks ) e iterar sobre esses clientes usando um loop WHILE:Isso deve funcionar com qualquer tabela, desde que você possa definir algum tipo de
ORDER BY
em alguma coluna.fonte
Ok, então eu nunca colocaria esse código em produção, mas ele atende aos seus requisitos.
fonte
A resposta de Marc é boa (eu comentaria se pudesse descobrir como fazê-lo!)
Apenas pensei em apontar que talvez seja melhor alterar o loop para que o
SELECT
único exista uma vez (em um caso real em que eu precisei fazer isso,SELECT
era bastante complexo e escrevê-lo duas vezes era um problema de manutenção arriscado).fonte
Se você pode transformar o procedimento armazenado em uma função que retorna uma tabela, poderá usar a aplicação cruzada.
Por exemplo, digamos que você tenha uma tabela de clientes e deseje calcular a soma de seus pedidos, criaria uma função que pegasse um CódigoDoCliente e retornasse a soma.
E você pode fazer isso:
Onde a função se pareceria:
Obviamente, o exemplo acima pode ser feito sem uma função definida pelo usuário em uma única consulta.
A desvantagem é que as funções são muito limitadas - muitos dos recursos de um procedimento armazenado não estão disponíveis em uma função definida pelo usuário e a conversão de um procedimento armazenado em uma função nem sempre funciona.
fonte
Eu usaria a resposta aceita, mas outra possibilidade é usar uma variável de tabela para armazenar um conjunto numerado de valores (nesse caso, apenas o campo ID de uma tabela) e percorrer os números de linha com um JOIN na tabela para recupere o que for necessário para a ação dentro do loop.
fonte
Para o SQL Server 2005 em diante, você pode fazer isso com o CROSS APPLY e uma função com valor de tabela.
Apenas para maior clareza, estou me referindo aos casos em que o procedimento armazenado pode ser convertido em uma função com valor de tabela.
fonte
Esta é uma variação da solução n3rds acima. Nenhuma classificação usando ORDER BY é necessária, pois MIN () é usado.
Lembre-se de que CustomerID (ou qualquer outra coluna numérica usada para o progresso) deve ter uma restrição exclusiva. Além disso, para torná-lo o mais rápido possível, o CustomerID deve estar indexado.
Eu uso essa abordagem em alguns varchars que preciso examinar, colocando-os em uma tabela temporária primeiro, para fornecer um ID.
fonte
Se você não usar o cursor, acho que precisará fazê-lo externamente (pegue a tabela e execute cada instrução e sempre que chamar sp). É o mesmo que usar um cursor, mas apenas fora SQL Por que você não usa um cursor?
fonte
Essa é uma variação das respostas já fornecidas, mas deve ter um desempenho melhor porque não requer ORDER BY, COUNT ou MIN / MAX. A única desvantagem dessa abordagem é que você precisa criar uma tabela temporária para armazenar todos os IDs (a suposição é de que existem lacunas na sua lista de IDs do cliente).
Dito isto, eu concordo com @Mark Powell, embora, de um modo geral, uma abordagem baseada em conjunto ainda deva ser melhor.
fonte
Eu costumo fazer dessa maneira quando há algumas linhas:
(Em conjuntos de dados maiores, eu usaria uma das soluções mencionadas acima).
fonte
DELIMITER //
fonte
Uma solução melhor para isso é
Foi assim que você obteve uma saída em formato de tabela limpa. Enquanto se você executa o SP para cada linha, obtém um resultado de consulta separado para cada iteração que é feia.
fonte
Caso o pedido seja importante
fonte
Eu tinha um código de produção que só podia lidar com 20 funcionários por vez, abaixo está a estrutura do código. Acabei de copiar o código de produção e removi as coisas abaixo.
fonte
Eu gosto de fazer algo semelhante a isso (embora ainda seja muito parecido com o uso de um cursor)
[código]
[/código]
Observe que você não precisa da identidade ou da coluna isIterated na sua tabela temporária / variável, eu prefiro fazê-lo dessa maneira, para não precisar excluir o registro superior da coleção enquanto iteramos no loop.
fonte