Comment et quand utiliser sys_refcursor dans Oracle

10

Quelqu'un peut-il me donner une petite explication sur comment et quand quelqu'un doit-il utiliser sys_refcursor?

Alejandro Bastidas
la source

Réponses:

10

Un curseur est un pointeur sur un jeu de résultats pour une requête. En renvoyant un, sys_refcursorvous autorisez le client à récupérer autant ou quelques-unes des lignes de la requête qu'il le souhaite. Dans les applications avec état, cela peut être utilisé pour parcourir les résultats.

Un curseur peut offrir plus de flexibilité que d'écrire une fonction PL / SQL qui retourne un tableau car c'est au client de décider du nombre de lignes à récupérer et du moment de s'arrêter. Cela dit, je n'ai pas trouvé beaucoup de cas où cette flexibilité supplémentaire est utile.

Il convient de noter que le sys_refcursorest faiblement typé, vous pouvez donc renvoyer des pointeurs vers des requêtes qui ont non seulement des clauses différentes de ou where, mais également des nombres et des types de colonnes différents. Vous pouvez également utiliser un curseur fortement typé où les colonnes du jeu de résultats sont fixes.

Cela vous permet d'écrire des fonctions qui renvoient différentes requêtes, comme ceci:

create function get_data ( type varchar2 ) return sys_refcursor as
  ret_cur sys_refcursor;
begin

  if type = 'EMP' then
    open ret_cur for select * from emp;
  elsif type = 'DEPT' then
    open ret_cur for select * from dept;
  end if;

  return ret_cur;
end;

Cependant, si vous utilisez sys_refcursorpour créer une fonction générique "ouvrir une requête" comme ci-dessus, vous faites probablement quelque chose de mal!

Chris Saxon
la source
@Chris ... pourquoi votre exemple de fonction est "faux?"
Johnny Wu
2
@JohnnyWu, une fonction "obtenez-moi n'importe quoi" sera plus difficile à gérer. Comment testez-vous pour vous assurer d'obtenir les bons résultats dans tous les cas? Et la sécurité? Cela peut être nécessaire si vous créez un cadre. Mais pour la logique commerciale générale, il est préférable d'avoir des fonctions distinctes get_empsetget_depts
Chris Saxon
1

Comme exemple des possibilités: parce que c'est pl / sql à l'arrière, on peut définir un objet pour représenter une ligne, définir une table pl / sql de ces objets,

create type T_MY_TABLE as table of t_my_object;

et terminer avec

OPEN p_recordset FOR select * from table( v_my_table );

Ainsi, plutôt que de construire des requêtes directes mongo, souvent denses et / ou cryptiques sur une table de base de données, on peut créer une table interne et avoir toute la puissance de pl / sql pour la remplir. Et le client qui recueille l'ensemble de résultats n'est pas plus sage. Et changer la définition de la table interne est plus facile à partir d'un point de vue de gestion que de changer une table de base de données.

De plus, lorsque vous utilisez des générateurs de rapports comme Jasper, vous pouvez pousser le SQL hors du rapport et dans la base de données, et appeler simplement la procédure pour obtenir le jeu d'enregistrements, laissant le côté du rapport se concentrer sur la mise en forme.

J Bliss
la source