J'ai une procédure stockée qui modifie les données utilisateur d'une certaine manière. Je lui passe user_id et ça fait son truc. 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 cet user_id
Comment pourrais-je écrire une requête pour cela?
sql
sql-server
stored-procedures
MetaGuru
la source
la source
Réponses:
utiliser un curseur
ADDENDUM: [exemple de curseur MS SQL]
dans MS SQL, voici un exemple d'article
notez que les curseurs sont plus lents que les opérations basées sur un ensemble, mais plus rapides que les boucles while manuelles; plus de détails dans cette question SO
ADDENDUM 2: si vous allez traiter plus que quelques enregistrements, insérez-les d'abord dans une table temporaire et passez le curseur sur la table temporaire; cela empêchera SQL de dégénérer en verrous de table et accélérera le fonctionnement
ADDENDUM 3: et bien sûr, si vous pouvez intégrer ce que votre procédure stockée fait à chaque ID utilisateur et exécuter le tout comme une seule instruction de mise à jour SQL, ce serait optimal
la source
essayez de changer votre méthode si vous avez besoin de boucler!
dans la procédure stockée parent, créez une table #temp qui contient les données que vous devez traiter. Appelez la procédure stockée enfant, la table #temp sera visible et vous pouvez la traiter, en espérant travailler avec l'ensemble des données et sans curseur ni boucle.
cela dépend vraiment de ce que fait cette procédure stockée enfant. Si vous effectuez une MISE À JOUR, vous pouvez "mettre à jour à partir de" rejoindre la table #temp et faire tout le travail en une seule instruction sans boucle. La même chose peut être faite pour INSERT et DELETE. Si vous devez effectuer plusieurs mises à jour avec des IF, vous pouvez les convertir en plusieurs
UPDATE FROM
avec la table #temp et utiliser des instructions CASE ou des conditions WHERE.Lorsque vous travaillez dans une base de données, essayez de perdre l'état d'esprit de la boucle, c'est un véritable drain de performance, provoquera un verrouillage / blocage et ralentira le traitement. Si vous bouclez partout, votre système ne sera pas très évolutif et sera très difficile à accélérer lorsque les utilisateurs commenceront à se plaindre de rafraîchissements lents.
Publiez le contenu de cette procédure que vous souhaitez appeler dans une boucle, et je parierai 9 fois sur 10, vous pouvez l'écrire pour travailler sur un ensemble de lignes.
la source
Quelque chose comme cette substitution sera nécessaire pour vos tables et noms de champs.
la source
Vous pouvez le faire avec une requête dynamique.
la source
Cela ne peut-il pas être fait avec une fonction définie par l'utilisateur pour répliquer tout ce que fait votre procédure stockée?
où udfMyFunction est une fonction que vous créez qui prend l'ID utilisateur et fait tout ce que vous devez en faire.
Voir http://www.sqlteam.com/article/user-defined-functions pour un peu plus d'informations
Je conviens que les curseurs doivent vraiment être évités dans la mesure du possible. Et c'est généralement possible!
(bien sûr, ma réponse présuppose que vous êtes uniquement intéressé à obtenir la sortie du SP et que vous ne modifiez pas les données réelles. Je trouve "modifie les données utilisateur d'une certaine manière" un peu ambiguë par rapport à la question d'origine, alors j'ai pensé que j'offrirais cela comme une solution possible. Tout dépend de ce que vous faites!)
la source
Utilisez une variable de table ou une table temporaire.
Comme cela a été mentionné précédemment, un curseur est un dernier recours. Principalement parce qu'il utilise beaucoup de ressources, émet des verrous et peut être un signe que vous ne comprenez pas comment utiliser SQL correctement.
Créez une variable de table comme celle-ci (si vous travaillez avec beaucoup de données ou si vous manquez de mémoire, utilisez un plutôt table temporaire ):
C'est
id
important.Remplacez
parent
etchild
par de bonnes données, par exemple des identifiants pertinents ou l'ensemble des données à exploiter.Insérez des données dans le tableau, par exemple:
Déclarez quelques variables:
Et enfin, créez une boucle while sur les données du tableau:
La première sélection récupère les données de la table temporaire. La seconde sélection met à jour le @id.
MIN
renvoie null si aucune ligne n'a été sélectionnée.Une autre approche consiste à boucler pendant que la table contient des lignes
SELECT TOP 1
et à supprimer la ligne sélectionnée de la table temporaire:la source
J'aime la manière de requête dynamique de Dave Rincon car elle n'utilise pas de curseurs et est petite 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 ça aidera quelqu'un...
la source