Comment appeler une procédure stockée pour chaque ligne d'une table, où les colonnes d'une ligne sont des paramètres d'entrée dans le sp sans utiliser de curseur?
sql
sql-server
stored-procedures
cursor
Johannes Rudolph
la source
la source
Réponses:
D'une manière générale, je recherche toujours une approche basée sur les ensembles (parfois au détriment du changement de schéma).
Cependant, cet extrait a sa place.
la source
Vous pouvez faire quelque chose comme ceci: classer votre table par exemple par CustomerID (en utilisant l'
Sales.Customer
exemple de table AdventureWorks ), et parcourir ces clients en utilisant une boucle WHILE:Cela devrait fonctionner avec n'importe quelle table tant que vous pouvez définir une sorte de
ORDER BY
sur une colonne.la source
Ok, donc je ne mettrais jamais un tel code en production, mais il répond à vos exigences.
la source
La réponse de Marc est bonne (je la commenterais si je pouvais trouver comment faire!)
Je pensais juste souligner qu'il serait peut-être préférable de changer la boucle pour
SELECT
que la boucle n'existe qu'une seule fois (dans un cas réel où je devais faire cela,SELECT
c'était assez complexe et l'écrire deux fois était un problème de maintenance risqué).la source
Si vous pouvez transformer la procédure stockée en une fonction qui renvoie une table, vous pouvez utiliser l'application croisée.
Par exemple, supposons que vous ayez une table de clients et que vous souhaitiez calculer la somme de leurs commandes, vous créeriez une fonction qui a pris un CustomerID et renvoyé la somme.
Et vous pouvez faire ceci:
À quoi ressemblerait la fonction:
De toute évidence, l'exemple ci-dessus pourrait être fait sans fonction définie par l'utilisateur dans une seule requête.
L'inconvénient est que les fonctions sont très limitées - de nombreuses fonctionnalités d'une procédure stockée ne sont pas disponibles dans une fonction définie par l'utilisateur et la conversion d'une procédure stockée en fonction ne fonctionne pas toujours.
la source
J'utiliserais la réponse acceptée, mais une autre possibilité consiste à utiliser une variable de table pour contenir un ensemble numéroté de valeurs (dans ce cas, juste le champ ID d'une table) et à parcourir celles-ci par numéro de ligne avec une jointure à la table pour récupérez tout ce dont vous avez besoin pour l'action dans la boucle.
la source
À partir de SQL Server 2005, vous pouvez le faire avec CROSS APPLY et une fonction table.
Pour plus de clarté, je fais référence aux cas où la procédure stockée peut être convertie en une fonction table.
la source
Il s'agit d'une variante de la solution n3rds ci-dessus. Aucun tri à l'aide de ORDER BY n'est nécessaire, car MIN () est utilisé.
N'oubliez pas que CustomerID (ou toute autre colonne numérique que vous utilisez pour la progression) doit avoir une contrainte unique. De plus, pour le rendre aussi rapide que possible, CustomerID doit être indexé sur.
J'utilise cette approche sur certains varchars que je dois examiner, en les mettant d'abord dans une table temporaire, pour leur donner un identifiant.
la source
Si vous ne savez pas quoi utiliser un curseur, je pense que vous devrez le faire en externe (obtenir la table, puis exécuter pour chaque instruction et à chaque fois appeler le sp) c'est la même chose que d'utiliser un curseur, mais seulement à l'extérieur SQL. Pourquoi n'utilisez-vous pas de curseur?
la source
Ceci est une variante des réponses déjà fournies, mais devrait être plus performant car il ne nécessite pas ORDER BY, COUNT ou MIN / MAX. Le seul inconvénient de cette approche est que vous devez créer une table temporaire pour contenir tous les ID (l'hypothèse est que vous avez des lacunes dans votre liste de CustomerID).
Cela dit, je suis d'accord avec @Mark Powell bien que, d'une manière générale, une approche basée sur un ensemble devrait toujours être meilleure.
la source
Je le fais généralement de cette façon quand il y a pas mal de lignes:
(Sur de plus grands ensembles de données, j'utiliserais l'une des solutions mentionnées ci-dessus).
la source
DELIMITER //
la source
Une meilleure solution pour cela est de
C'est ainsi que vous obtenez une sortie au format table propre. Alors que si vous exécutez SP pour chaque ligne, vous obtenez un résultat de requête distinct pour chaque itération, ce qui est laid.
la source
Dans le cas où la commande est importante
la source
J'avais un code de production qui ne pouvait gérer que 20 employés à la fois, voici le cadre du code. Je viens de copier le code de production et de supprimer les éléments ci-dessous.
la source
J'aime faire quelque chose de similaire (même si c'est toujours très similaire à l'utilisation d'un curseur)
[code]
[/code]
Notez que vous n'avez pas besoin de l'identité ou de la colonne isIterated sur votre table temp / variable, je préfère simplement le faire de cette façon afin de ne pas avoir à supprimer le premier enregistrement de la collection lorsque je parcours la boucle.
la source