Comment puis-je exécuter une procédure stockée une fois pour chaque ligne retournée par la requête?
J'ai une procédure stockée qui modifie les données de l'utilisateur dans une certaine manière. Je le passe user_id et il le fait de la chose. Je veux exécuter une requête sur une table, puis pour chaque user_id je trouve exécuter la procédure stockée une fois sur que user_id
Comment pourrais-je écrire des requêtes pour cet?
- Vous devez spécifier quel SGBDR - la réponse sera différente pour SQL Server, Oracle, MySql, etc.
- Les Chances sont que vous n'avez pas besoin d'une procédure stockée à tous. Pouvez-vous décrire "ce que" la procédure stockée n', exactement? Peut-être l'ensemble du processus peut être exprimée comme une seule instruction de mise à jour. "Le faire une fois pour chaque enregistrement" modèle doit généralement être évitée, si possible.
- La base de données utilisez-vous?
- Il est préférable si vous pouvez éviter cela. La plupart des bases de données optimisé pour le jeu en fonction des actions, et la mise en boucle à l'aide d'un curseur sera relativement lente. Cela dit, voici un bon exemple pour savoir comment faire cela à l'aide de SQL Server
- Vous devriez lire cet article... article 2 dit de NE PAS utiliser des curseurs codeproject.com/KB/database/sqldodont.aspx...mind je suis aussi contre l'optimisation prématurée.
- codeproject.com/KB/database/sqldodont.aspx essayer de nouveau
- Si vous lisez plus loin dans ce mal écrit l'article, vous verrez que le point 10 est "de NE PAS utiliser des curseurs côté serveur, Sauf si vous savez ce que vous faites." Je pense que c'est un cas de "je sais ce que je fais".
- devrait être votre manière préférée de tuer les performances du système tout entier." Hilarant. Je veux dire, correspond à mon cas d'utilisation exactement.
Vous devez vous connecter pour publier un commentaire.
utiliser un curseur
ADDENDUM: [MS SQL curseur exemple]
dans MS SQL, voici un exemple d'article
noter que les curseurs sont plus lents que les opérations à base d'ensemble, mais plus rapide que manuel tout-boucles; plus de détails dans cette SORTE de question
ADDENDUM 2: si vous allez traiter plus que juste un peu d'enregistrements, de les attirer dans une table temporaire première et exécuter le curseur au-dessus de la table temporaire; cela permettra d'éviter SQL à partir de l'escalade dans la table des verrous et accélérer le fonctionnement
L'ADDITIF 3: et bien sûr, si vous pouvez inline quel que soit votre procédure stockée pour chaque ID d'utilisateur et exécuter l'ensemble comme une seule instruction SQL update, qui serait optimal
essayez de changer votre méthode si vous avez besoin de boucle!
au sein de la parent d'une procédure stockée, créer un #temp table qui contient les données que vous devez traiter. Appelez l'enfant de la procédure stockée, le n ° de la table temporaire sera visible et vous pouvez les traiter, nous l'espérons travailler avec l'ensemble des données et sans curseur ou en boucle.
cela dépend vraiment de ce que cet enfant de la procédure stockée est en train de faire. Si vous êtes à la mise à JOUR-ing, vous pouvez "mettre à jour à partir de" se joindre à la table #temp et faire tout le travail en une seule instruction sans boucle. La même chose peut être faite pour l'INSERTION et la suppression. Si vous avez besoin de faire plusieurs mises à jour avec IFs, vous pouvez convertir plusieurs
UPDATE FROM
avec le n ° de la table temporaire et de CAS d'utilisation des déclarations ou LORSQUE les conditions.Lorsque vous travaillez dans une base de données d'essayer de perdre la mentalité de bouclage, c'est une véritable performance de vidange, seront la cause de verrouillage/bloquer et ralentir le traitement. Si vous en boucle partout, votre système ne sera pas l'échelle très bien, et il sera très dur pour accélérer lorsque les utilisateurs commencent à se plaindre de ralentir rafraîchit.
Publier le contenu de cette procédure que vous souhaitez appeler dans une boucle, et je parie que 9 fois sur 10, vous pouvez l'écrire à travailler sur un ensemble de lignes.
Quelque chose comme cela substitutions seront nécessaires pour vos tables et les noms de champ.
Vous pouvez le faire avec une requête dynamique.
Cela ne peut pas être fait avec une fonction définie par l'utilisateur pour répliquer quelque soit votre procédure stockée est en train de faire?
où udfMyFunction est une fonction que vous faites qui prend l'ID de l'utilisateur et fait tout ce que vous devez faire avec elle.
Voir http://www.sqlteam.com/article/user-defined-functions pour un peu plus de fond
Je suis d'accord que les curseurs vraiment devrait être évitée autant que possible. Et il est généralement possible!
(bien sûr, ma réponse suppose que vous êtes seulement intéressés par l'obtention de la sortie de la SP et que vous ne modifiez pas les données réelles. Je trouve "modifie les données de l'utilisateur, d'une certaine manière un peu ambiguë de la question d'origine, donc j'ai pensé l'offrir cela comme une solution possible. Totalement dépend de ce que vous faites!)
Utiliser une variable de table ou une table temporaire.
Comme il a été mentionné précédemment, un curseur est un dernier recours. Surtout parce qu'il utilise beaucoup de ressources, les problèmes de serrures et pourrait être un signe que vous êtes tout simplement pas comprendre comment utiliser SQL correctement.
Créer une variable de table comme ceci (si vous travaillez avec un grand nombre de données, ou sont à court de mémoire, utilisez un table temporaire place):
La
id
est important.Remplacer
parent
etchild
avec quelques bonnes données, par exemple, à des identifiants ou l'ensemble de données doit être opéré.Insérer des données dans la table, par exemple:
Déclarer quelques variables:
Et enfin, créer une boucle while sur les données de la table:
Du premier select récupère des données à partir de la table temporaire. La deuxième sélectionnez les mises à jour de l' @id.
MIN
renvoie la valeur null si aucune ligne n'a été sélectionnée.Une approche alternative consiste à boucle pendant que la table contient des lignes,
SELECT TOP 1
et de supprimer la ligne sélectionnée de la table temporaire:J'aime la dynamique de la requête façon de Dave Rincon qu'elle n'utilise les curseurs et est petit et facile. Merci Dave pour le partage.
Mais pour mes besoins sur Azure SQL et avec un "distinct" dans la requête, j'ai dû modifier le code comme ceci:
J'espère que cela aide quelqu'un...