Quelle est la différence entre les curseurs explicites et implicites dans Oracle?

StackOverflow https://stackoverflow.com/questions/74010

  •  09-06-2019
  •  | 
  •  

Question

Je suis un peu rouillé sur mon jargon de curseur en PL / SQL. Quelqu'un le sait?

Était-ce utile?

La solution

Un curseur implicite est un curseur "automatiquement". pour vous par Oracle lorsque vous exécutez une requête. Il est plus simple de coder, mais souffre de

  • inefficacité (la norme ANSI spécifie qu’il faut extraire deux fois pour vérifier s’il existe plusieurs enregistrements)
  • vulnérabilité aux erreurs de données (si vous obtenez deux lignes, une exception TOO_MANY_ROWS est générée)

Exemple

SELECT col INTO var FROM table WHERE something;

Un curseur explicite est celui que vous créez vous-même. Cela prend plus de code, mais donne plus de contrôle - par exemple, vous pouvez simplement ouvrir-récupérer-fermer si vous ne voulez que le premier enregistrement et ne vous souciez pas de l'existence d'autres.

Exemple

DECLARE   
  CURSOR cur IS SELECT col FROM table WHERE something; 
BEGIN
  OPEN cur;
  FETCH cur INTO var;
  CLOSE cur;
END;

Autres conseils

Un curseur explicite est défini comme tel dans un bloc de déclaration:

DECLARE 
CURSOR cur IS 
  SELECT columns FROM table WHERE condition;
BEGIN
...

un curseur implicite est implémenté directement dans un bloc de code:

...
BEGIN
   SELECT columns INTO variables FROM table where condition;
END;
...

1.CURSOR: Lorsque PLSQL envoie des instructions SQL, il crée un espace de travail privé.    analyser & amp; exécuter l'instruction SQL s'appelle le curseur.

2.IMPLICIT: Lorsqu'un bloc PL / SQLexecutable émet une instruction SQL.    PL / SQL crée un curseur implicite et gère automatiquement les moyens    implcit ouvert & amp; la fermeture a lieu. Il a utilisé quand SQL retour instruction    une seule ligne.Il possède 4 attributs SQL% ROWCOUNT, SQL% FOUND,    SQL% NOTFOUND, SQL% ISOPEN.

3.EXPLICIT: il est créé & amp; géré par le programmeur. Il a besoin de tous    time explicit open, fetch & amp; Fermer. Il est utilisé lors de l'instruction sql    renvoie plus d'une ligne. Il a aussi 4 attributs    CUR_NAME% ROWCOUNT, CUR_NAME% FOUND, CUR_NAME% NOTFOUND,    CUR_NAME% ISOPEN. Il traite plusieurs lignes en utilisant une boucle.    Le programmeur peut également passer le paramètre au curseur explicite.

  • Exemple: curseur explicite

& nbsp;

declare 
   cursor emp_cursor 
   is 
   select id,name,salary,dept_id 
   from employees; 
   v_id employees.id%type; 
   v_name employees.name%type; 
   v_salary employees.salary%type; 
   v_dept_id employees.dept_id%type; 
   begin 
   open emp_cursor; 
   loop 
   fetch emp_cursor into v_id,v_name,v_salary,v_dept_id; 
   exit when emp_cursor%notfound;
   dbms_output.put_line(v_id||', '||v_name||', '||v_salary||','||v_dept_id); 
   end loop;                    
   close emp_cursor; 
   end;

Un curseur explicite est celui que vous déclarez, par exemple:

CURSOR my_cursor IS
  SELECT table_name FROM USER_TABLES

Un curseur implicite est un curseur créé pour prendre en charge tout SQL en ligne que vous écrivez (statique ou dynamique).

En réponse à la première question. Directement depuis l’Oracle documentation . / p>

  

Un curseur est un pointeur sur un SQL privé.   zone qui stocke des informations sur   traiter un SELECT ou un DML spécifique   déclaration.

Les curseurs implicites nécessitent une mémoire tampon anonyme.

Les curseurs explicites peuvent être exécutés encore et encore en utilisant leur nom. Ils sont stockés dans un espace mémoire défini par l'utilisateur plutôt que dans une mémoire tampon anonyme et sont donc facilement accessibles par la suite.

Avec les curseurs explicites, vous avez un contrôle complet sur la manière d’accéder aux informations de la base de données. Vous décidez quand OUVRIR le curseur, quand FETCH enregistre à partir du curseur (et donc de la ou des tables dans l'instruction SELECT du curseur), combien d'enregistrements à extraire et quand FERMER le curseur. Des informations sur l'état actuel de votre curseur sont disponibles en examinant les attributs du curseur.

Voir http://www.unix.com.ua/ orelly / oracle / prog2 / ch06_03.htm pour plus de détails.

Google est votre ami: http://docstore.mik.ua/ orelly / oracle / prog2 / ch06_03.htm

  

PL / SQL émet un curseur implicite   chaque fois que vous exécutez une instruction SQL   directement dans votre code, tant que cela   le code n'emploie pas explicitement   le curseur. C'est ce qu'on appelle un "implicite"   curseur parce que vous, le développeur, faites   pas explicitement déclarer un curseur pour   l'instruction SQL.

     

Un curseur explicite est un SELECT   déclaration explicitement définie   dans la section déclaration de votre   code et, dans le processus, assigné un   prénom. Il n’existe pas de   curseur explicite pour UPDATE, DELETE,   et INSERT déclarations.

Un curseur est une fenêtre SÉLECTIONNÉE sur une table Oracle. Il s’agit d’un groupe d’enregistrements présents dans une table Oracle et satisfaisant à certaines conditions. Un curseur peut aussi SÉLECTIONNER tout le contenu d'une table. Avec un curseur, vous pouvez manipuler les colonnes Oracle, en les aliasant dans le résultat. Voici un exemple de curseur implicite:

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      FOR C1_REC IN C1
      LOOP
         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;
   END;
END;
/

Avec FOR ... LOOP ... END LOOP, vous ouvrez et fermez automatiquement le curseur lorsque tous les enregistrements du curseur ont été analysés.

Voici un exemple de curseur explicite:

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      OPEN c1;

      LOOP
         FETCH c1 INTO c1_rec;

         EXIT WHEN c1%NOTFOUND;

         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;

      CLOSE c1;
   END;
END;
/

Dans le curseur explicite, vous ouvrez et fermez le curseur de manière explicite, en vérifiant la présence d'enregistrements et en indiquant une condition de sortie.

Le curseur implicite ne renvoie qu'un seul enregistrement et est appelé automatiquement. Cependant, les curseurs explicites sont appelés manuellement et peuvent renvoyer plusieurs enregistrements.

Je sais que c'est une vieille question, mais je pense qu'il serait bon d'ajouter un exemple concret pour montrer la différence entre les deux du point de vue des performances.

Du point de vue des performances, les curseurs implicites sont plus rapides.

Voyons la différence de performance entre les deux:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2    l_loops  NUMBER := 100000;
  3    l_dummy  dual.dummy%TYPE;
  4    l_start  NUMBER;
  5
  6    CURSOR c_dual IS
  7      SELECT dummy
  8      FROM   dual;
  9  BEGIN
 10    l_start := DBMS_UTILITY.get_time;
 11
 12    FOR i IN 1 .. l_loops LOOP
 13      OPEN  c_dual;
 14      FETCH c_dual
 15      INTO  l_dummy;
 16      CLOSE c_dual;
 17    END LOOP;
 18
 19    DBMS_OUTPUT.put_line('Explicit: ' ||
 20                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 21
 22    l_start := DBMS_UTILITY.get_time;
 23
 24    FOR i IN 1 .. l_loops LOOP
 25      SELECT dummy
 26      INTO   l_dummy
 27      FROM   dual;
 28    END LOOP;
 29
 30    DBMS_OUTPUT.put_line('Implicit: ' ||
 31                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 32  END;
 33  /
Explicit: 332 hsecs
Implicit: 176 hsecs

PL/SQL procedure successfully completed.

Ainsi, une différence significative est clairement visible.

Autres exemples ici .

En PL / SQL, un curseur est un pointeur sur cette zone de contexte. Il contient toutes les informations nécessaires au traitement de la déclaration.

Curseurs implicites: Les curseurs implicites sont automatiquement créés par Oracle chaque fois qu'une instruction SQL est exécutée, lorsqu'il n'existe aucun curseur explicite pour cette instruction. Les programmeurs ne peuvent pas contrôler les curseurs implicites et les informations qu’ils contiennent.

Curseurs explicites: Les curseurs explicites sont des curseurs définis par le programmeur permettant de mieux contrôler la zone de contexte. Un curseur explicite doit être défini dans la section déclaration du bloc PL / SQL. Il est créé sur une instruction SELECT qui renvoie plusieurs lignes.

La syntaxe pour créer un curseur explicite est:

CURSOR cursor_name IS select_statement; 

Chaque instruction SQL exécutée par la base de données Oracle est associée à un curseur, qui est une zone de travail privée pour stocker les informations de traitement. Des curseurs implicites sont créés implicitement par le serveur Oracle pour toutes les instructions DML et SELECT.

Vous pouvez déclarer et utiliser des curseurs Explicit pour nommer la zone de travail privée et accéder à ses informations stockées dans votre bloc de programme.

Comme indiqué dans d'autres réponses, les curseurs implicites sont plus faciles à utiliser et moins sujets aux erreurs.

Et Curseurs implicite / explicite dans Oracle PL / SQL montre que les curseurs implicites sont jusqu'à deux fois plus rapides que les curseurs explicites également.

Il est étrange que personne n'ait encore mentionné Implicitement pour LO LOOP Curseur :

begin
  for cur in (
    select t.id from parent_trx pt inner join trx t on pt.nested_id = t.id
    where t.started_at > sysdate - 31 and t.finished_at is null and t.extended_code is null
  )
  loop
    update trx set finished_at=sysdate, extended_code = -1 where id = cur.id;
    update parent_trx set result_code = -1 where nested_id = cur.id;
  end loop cur;
end;

Un autre exemple sur SO: PL / SQL POUR LE CURSEUR IMPLICITE DE BOUCLE .

C'est beaucoup plus court que la forme explicite.

Ceci fournit également une solution de contournement intéressante pour mettre à jour plusieurs tables à partir de CTE .

Explicite ...

le curseur foo est select * from blah; commencer    ouvrir chercher sortir quand fermer le curseur yada yada yada

ne les utilisez pas, utilisez implicite

le curseur foo est choisi * parmi blah;

pour n in foo loop    x = n.some_column boucle de fin

Je pense que vous pouvez même le faire

pour n dans la boucle (select * from blah) ...

Tenez-vous en à l’implicite, ils se ferment, ils sont plus lisibles, ils facilitent la vie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top