Il est basé sur la question d'entrevue que j'ai rencontrée.
Une définition très courte peut être
Il peut être utilisé pour manipuler les lignes renvoyées par une requête.
Outre l'utilisation du curseur (les points sont répertoriés ici sur MSDN), j'ai une question dans mon esprit que si nous pouvons effectuer toutes les opérations à l'aide d'une requête ou d'une procédure stockée (si je ne me trompe pas, Comme nous pouvons utiliser Transact-SQL pour ms-sql), y a-t-il un point concret que nous devrions utiliser le curseur?
Utiliser des curseurs par rapport à de grands ensembles de résultats, c'est comme utiliser le streaming vidéo au lieu de télécharger une vidéo d'un seul coup et de la regarder lorsqu'elle a été téléchargée. Si vous téléchargez, vous devez avoir quelques Go d'espace et la patience d'attendre la fin du téléchargement. Maintenant, quelle que soit la vitesse de votre machine ou de votre réseau, tout le monde regarde un film à la même vitesse.
Normalement, toute requête est envoyée au serveur, exécutée et l'ensemble de résultats vous est envoyé sur le réseau, en une seule rafale d'activité. Le curseur vous donnera accès aux données ligne par ligne et ne diffusera chaque ligne que lorsque vous en aurez fait la demande (vous pourrez en fait les visualiser).
Ce qui nous amène cependant à quelques mises en garde:
Cohérence: à l'aide d'un curseur, vous n'opérez (généralement) pas sur un instantané cohérent des données, mais sur une ligne. Ainsi, vos garanties de concurrence/cohérence/isolation passent de la base de données entière (ACID) à une seule ligne. Vous pouvez généralement informer votre SGBD du niveau de concurrence que vous souhaitez, mais si vous êtes trop exigeant (verrouiller la table complète dans laquelle vous vous trouvez), vous gaspillerez de nombreuses économies de ressources côté serveur.
La transmission de chaque ligne par elle-même peut être très inefficace, car chaque paquet a une surcharge de négociation que vous pourriez éviter en envoyant de gros morceaux, peut-être compressés, de données par paquet. (Aucun serveur de base de données ou bibliothèque cliente n'est assez stupide pour transmettre chaque ligne individuellement, il y a mise en cache et segmentation aux deux extrémités, toujours, c'est pertinent.)
Les curseurs sont plus difficiles à bien faire. Considérez une requête avec un grand ensemble de résultats, vous motivant à utiliser un curseur, qui utilise une clause GROUP BY avec des fonctions d'agrégation. (De telles requêtes sont courantes dans les entrepôts de données). Le GROUP BY peut complètement mettre à la corbeille votre serveur, car il doit générer et stocker l'ensemble de résultats en une seule fois, peut-être même maintenir des verrous sur d'autres tables.
Règle générale:
"Nature séquentielle" signifie qu'il n'y a pas de fonctions d'agrégation dans les lourdes clauses GROUP BY dans votre requête. Le serveur peut décider paresseusement de calculer 10 lignes pour que votre curseur consomme à partir d'un cache et faire d'autres choses en attendant.
HTH
Un curseur est un outil qui vous permet d'itérer les enregistrements d'un ensemble. Il a des concepts de ordre et enregistrement courant.
Généralement, SQL
fonctionne avec des multisets: ce sont des ensembles d'enregistrements pouvant se répéter dans un ordre donné, pris dans leur ensemble.
Dites, cette requête:
SELECT *
FROM a
JOIN b
ON b.a = a.id
, fonctionne sur les multisets a
et b
.
Rien dans cette requête ne fait d'hypothèses sur l'ordre des enregistrements, comment ils sont stockés, dans quel ordre ils doivent être consultés, etc.
Cela permet d'abstraire les détails d'implémentation et de laisser le système essayer de choisir le meilleur algorithme possible pour exécuter cette requête.
Cependant, après avoir transformé toutes vos données, vous devrez finalement accéder aux enregistrements de manière ordonnée et un par un.
Vous ne vous souciez pas de la façon dont les entrées d'un répertoire sont stockées sur un disque dur, mais une imprimante nécessite qu'elles soient introduites dans l'ordre alphabétique; et les balises de mise en forme doivent être appliquées à chaque enregistrement individuellement.
C'est exactement là que les curseurs entrent en jeu. Chaque fois que vous traitez un jeu de résultats côté client, vous utilisez un curseur. Vous n'obtenez pas de mégaoctets de données non triées du serveur: vous obtenez simplement une petite variable: un descripteur d'ensemble de résultats, et écrivez simplement quelque chose comme ceci:
while (!rs.EOF) {
process(rs);
rs.moveNext();
}
C'est le curseur qui implémente tout cela pour vous.
Cela concerne bien sûr l'interaction base de données-client.
Quant à la base de données elle-même: à l'intérieur la base de données, vous avez rarement besoin des curseurs, car, comme je l'ai dit ci-dessus, presque toutes les transformations de données peuvent être implémentées en utilisant des opérations d'ensemble plus efficacement.
Cependant, il existe des exceptions:
SQL Server
sont très mal implémentés. Une somme cumulée, par exemple, pourrait être calculée beaucoup plus efficacement avec un curseur que l'utilisation des opérations basées sur un ensembleVous pouvez également trouver cet article intéressant à lire:
À l'aide d'un curseur, il est possible de lire séquentiellement un ensemble de données, par programmation, afin qu'il se comporte de la même manière que l'accès aux fichiers conventionnel, plutôt que la caractéristique de comportement basée sur un ensemble de SQL.
Il y a quelques situations où cela peut être utile:
Où il est nécessaire de simuler un comportement d'accès aux enregistrements basé sur des fichiers - par exemple, lorsqu'une base de données relationnelle est utilisée comme mécanisme de stockage de données pour un morceau de code qui a été précédemment écrit pour utiliser des fichiers indexés pour le stockage de données.
Lorsqu'il est nécessaire de traiter les données de manière séquentielle - un exemple simple pourrait être de calculer un solde total cumulé pour un client spécifique. (Un certain nombre de bases de données relationnelles, telles qu'Oracle et SQLServer, ont désormais des extensions analytiques pour SQL qui devraient considérablement réduire le besoin de cela.)
Inévitablement, wikipedia a plus: http://en.wikipedia.org/wiki/Database_cursor
Parfois, une logique basée sur un ensemble peut devenir assez complexe et opaque. Dans ces cas et si les performances ne sont pas un problème, un curseur côté serveur peut être utilisé pour remplacer la logique relationnelle par une logique procédurale plus gérable et familière (pour un penseur non relationnel), ce qui facilite la maintenance.
Avec le curseur, vous accédez à une ligne à la fois. Il est donc bon de l'utiliser lorsque vous souhaitez manipuler avec beaucoup de lignes mais avec une seule à la fois.
On m'a dit lors de mes cours, la raison d'utiliser le curseur est que vous voulez accéder à plus de lignes que vous ne pouvez en contenir - vous ne pouvez donc pas simplement obtenir toutes les lignes dans une collection, puis la parcourir.