Recherche…


Syntaxe

  • Curseur nom_curseur est votre_sélection_de_sélection
  • Curseur nom_curseur ( paramètre TYPE) est-ce que votre_select_statement_using_param
  • FOR x in ( your_select_statement ) LOOP ...

Remarques

Les curseurs déclarés sont difficiles à utiliser et vous devriez préférer les boucles FOR dans la plupart des cas. Ce qui est très intéressant dans les curseurs par rapport aux boucles FOR simples, c'est que vous pouvez les paramétrer.

Il est préférable d'éviter les boucles avec PL / SQL et les curseurs plutôt que d'utiliser Oracle SQL. Cependant, pour les personnes habituées au langage procédural, il peut être beaucoup plus facile à comprendre.

Si vous voulez vérifier si un enregistrement existe, puis faire des choses différentes selon que l'enregistrement existe ou non, il est logique d' utiliser des instructions MERGE dans des requêtes SQL ORACLE pures au lieu d'utiliser des boucles de curseur. (Veuillez noter que MERGE est uniquement disponible dans les versions Oracle> = 9i).

Curseur paramétrable "FOR loop"

DECLARE
  CURSOR c_emp_to_be_raised(p_sal emp.sal%TYPE) IS 
    SELECT * FROM emp WHERE  sal < p_sal;
BEGIN
  FOR cRowEmp IN c_emp_to_be_raised(1000) LOOP
    dbms_Output.Put_Line(cRowEmp .eName ||' ' ||cRowEmp.sal||'... should be raised ;)');
  END LOOP;
END;
/

Curseur implicite "FOR loop"

BEGIN
  FOR x IN (SELECT * FROM emp WHERE sal < 100) LOOP
    dbms_Output.Put_Line(x.eName ||' '||x.sal||'... should REALLY be raised :D');
  END LOOP;
END;
/
  • Le premier avantage est qu'il n'y a pas de déclaration fastidieuse à faire (pensez à cette horrible chose "CURSOR" que vous aviez dans les versions précédentes)
  • deuxième avantage est que vous construisez d'abord votre requête select, puis quand vous avez ce que vous voulez, vous pouvez immédiatement accéder aux champs de votre requête ( x.<myfield> ) dans votre boucle PL / SQL
  • La boucle ouvre le curseur et récupère un enregistrement à la fois pour chaque boucle. A la fin de la boucle, le curseur est fermé.
  • Les curseurs implicites sont plus rapides car le travail de l'interpréteur augmente à mesure que le code s'allonge. Le moins de code, moins l'interprète doit travailler.

Travailler avec SYS_REFCURSOR

SYS_REFCURSOR peut être utilisé comme type de retour lorsque vous devez manipuler facilement une liste renvoyée non pas par une table, mais plus précisément par une fonction:

fonction renvoyant un curseur

CREATE OR REPLACE FUNCTION list_of (required_type_in IN VARCHAR2)
   RETURN SYS_REFCURSOR
IS
   v_ SYS_REFCURSOR;
BEGIN
   CASE required_type_in
      WHEN 'CATS'
      THEN
         OPEN v_ FOR
           SELECT nickname FROM (
                select 'minou' nickname from dual
      union all select 'minâ'           from dual
      union all select 'minon'          from dual         
           );
      WHEN 'DOGS'
      THEN
         OPEN v_ FOR
              SELECT dog_call FROM (
                select 'bill'   dog_call from dual
      union all select 'nestor'          from dual
      union all select 'raoul'           from dual         
           );
   END CASE;
   -- Whit this use, you must not close the cursor.
   RETURN v_;
END list_of;
/

et comment l'utiliser:

DECLARE
   v_names   SYS_REFCURSOR;
   v_        VARCHAR2 (32767);
BEGIN
   v_names := list_of('CATS');
   LOOP
      FETCH v_names INTO v_;
      EXIT WHEN v_names%NOTFOUND;
      DBMS_OUTPUT.put_line(v_);
   END LOOP;
   -- here you close it
   CLOSE v_names;
END;
/

Manipulation d'un CURSEUR

  • Déclarez le curseur pour numériser une liste d'enregistrements
  • L'ouvrir
  • Récupère l'enregistrement actuel dans des variables (cette position d'incrémentation)
  • Utilisez %notfound pour détecter la fin de la liste
  • N'oubliez pas de fermer le curseur pour limiter la consommation de ressources dans le contexte actuel

-

DECLARE
  CURSOR curCols IS -- select column name and type from a given table
         SELECT column_name, data_type FROM all_tab_columns where table_name='MY_TABLE';
  v_tab_column all_tab_columns.column_name%TYPE;
  v_data_type all_tab_columns.data_type%TYPE;
  v_ INTEGER := 1;
BEGIN
  OPEN curCols;
  LOOP
     FETCH curCols INTO v_tab_column, v_data_type;
     IF curCols%notfound OR v_ > 2000 THEN
       EXIT;
     END IF;
     dbms_output.put_line(v_||':Column '||v_tab_column||' is of '|| v_data_type||' Type.');
     v_:= v_ + 1;
  END LOOP;

  -- Close in any case
  IF curCols%ISOPEN THEN  
     CLOSE curCols;
  END IF;
END;
/


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow