web-dev-qa-db-fra.com

Comment déclarer un curseur après BEGIN?

Je veux savoir si un curseur peut être déclaré après BEGIN.

Et comment puis-je exporter le résultat du plsql vers une feuille Excel, car je dois exécuter cette procédure en tant que travail?.

CREATE OR REPLACE PROCEDURE masc(v_amsprogramid VARCHAR2) AS

  v_mid VARCHAR2(50);
  v_sid VARCHAR2(50);

  CURSOR c1 IS
    SELECT DISTINCT mid
    FROM table_a WHERE aid = v_aid
    ORDER BY mid;

  BEGIN

    OPEN c1;

    LOOP
      FETCH c1 INTO v_mid;
      EXIT WHEN c1%NOTFOUND;

      DECLARE
        CURSOR c2 IS
          SELECT DISTINCT sid INTO v_sid
          FROM table_b WHERE mid = v_mid;

      BEGIN
        OPEN c2;
        LOOP

          FETCH c1 INTO v_mid;
          EXIT WHEN c1%NOTFOUND;

          dbms_output.PUT_LINE('MID : ' || v_mid);
          dbms_output.PUT_LINE('Sid : ' || v_sid);

        END LOOP;

        CLOSE c2;
      END LOOP;

      CLOSE c1;
  END masc;
6
olivia

Peut-être que vous recherchez ceci:

create or replace PROCEDURE MASC (V_AMSPROGRAMID VARCHAR2) AS

V_MID VARCHAR2(50);
V_SID VARCHAR2(50);

CURSOR C1 IS
SELECT distinct MID from table_a WHERE AID = V_AID
ORDER BY MID;

CURSOR C2 IS
SELECT DISTINCT SID INTO V_SID FROM table_b WHERE MID = V_MID
ORDER BY MID;

BEGIN    
...

ou 

create or replace PROCEDURE MASC (V_AMSPROGRAMID VARCHAR2) AS

V_MID VARCHAR2(50);
V_SID VARCHAR2(50);

CURSOR C1 IS
SELECT distinct MID from table_a WHERE AID = V_AID
ORDER BY MID;

CURSOR C2(v in NUMBER) IS
SELECT DISTINCT SID INTO V_SID FROM table_b WHERE MID = v
ORDER BY MID;

BEGIN

OPEN C1;
...
OPEN C2(V_MID);
...
3

Je veux savoir si je peux déclarer un curseur après avoir commencé

Pas exactement. Mais vous pouvez utiliser un curseur pour loop au lieu de déclarer un curseur explicite .

Par exemple,

FOR i IN (SELECT distinct MID from table_a WHERE AID = V_AID ORDER BY MID)
LOOP
   <do something>
END LOOP;

Quoi qu'il en soit, cela serait plus lent, car ligne par ligne, c'est lent. Je ne vois pas du tout besoin de procédure. Si vous avez vraiment besoin de le faire dans PL/SQL , alors considérez BULK COLLECT .

Et comment puis-je exporter le résultat du plsql vers une feuille Excel parce que je peux exécuter cette procédure en tant que travail.

Je ne vois pas la nécessité de PL/SQL dans ce cas. Vous pouvez simplement utiliserSPOOLin SQL * Plus .

Par exemple,

sqlplus user/pass@service_name
<required formatting options>

SPOOL /location/myfile.csv
SELECT distinct MID from table_a WHERE AID = V_AID ORDER BY MID;
SPOOL OFF
2
Lalit Kumar B

Vous pouvez déclarer plusieurs curseurs dans le même bloc pl/sql. Il n'est pas nécessaire de déclarer le deuxième curseur après avoir ouvert le premier curseur!

Vous écririez quelque chose comme:

create or replace procedure masc (p_amsprogramid varchar2)
as
  v_mid varchar2(50);
  v_sid varchar2(50);

  cursor c1 
  is
    select   distinct mid
    from     table_a
    where    aid = p_amsprogramid
    order by mid;

  cursor c2
  is
    select distinct sid
    from   table_b
    where  mid = v_mid;

begin
  open c1;
  loop
    fetch c1 into v_mid;
    exit when c1%notfound;

    open c2;
    loop
      fetch c1 into v_mid;
      exit when c1%notfound;

      dbms_output.put_line('mid : ' || v_mid);
      dbms_output.put_line('sid : ' || v_sid);
    end loop;

    close c2;
  end loop;

  close c1;
end masc;
/

Cependant, si vous deviez remplacer votre recherche de boucle-curseur-ouverte par un curseur de boucle, vous pourriez simplifier un peu les choses:

create or replace procedure masc (p_amsprogramid varchar2)
as
  cursor c1 
  is
    select   distinct mid
    from     table_a
    where    aid = p_amsprogramid
    order by mid;

  cursor c2
  is
    select distinct sid
    from   table_b
    where  mid = v_mid;

begin
  for rec1 in c1
  loop
    for rec2 in c2
    loop
      dbms_output.put_line('mid : ' || rec1.mid);
      dbms_output.put_line('sid : ' || rec2.sid);
    end loop;
  end loop;
end masc;
/

En regardant cela, vous avez une boucle de curseur imbriquée. Cela relève du raisonnement procédural plutôt que du raisonnement basé sur les ensembles, ce qui est plutôt un non-non quand vous travaillez avec des jeux de données dans la base de données (c'est-à-dire que c'est lent. Vous devez basculer constamment entre SQL et PL/Moteurs SQL, au lieu de simplement demander au moteur SQL de tout calculer avant de le transmettre au moteur PL/SQL).

En faisant la boucle de curseur imbriquée, vous réinventez les jointures NESTED LOOP - le moteur SQL peut faire beaucoup mieux que vous (sans mentionner que ce n'est peut-être pas la jointure la plus efficace, et le moteur SQL pourrait choisir un meilleur moyen de faire la jointure!). À chaque fois que vous voyez une boucle de curseur imbriquée, vous devezIMM&EACUTE;DIATEMENTvous arrêter pour voir si vous pouvez combiner les requêtes en une seule instruction de sélection. (En fait, chaque fois que vous voyez une boucle, vous devez faire une pause et déterminer si vous en avez vraiment besoin; parfois, cela est nécessaire, mais si vous faites quelque chose comme sélectionner un ensemble de résultats, puis parcourir chaque ligne puis faire une mise à jour, Envisagez de fusionner l'élément select dans la mise à jour afin d'obtenir une instruction mettant à jour toutes les lignes à la fois. Ce sera beaucoup plus rapide!)

Par exemple, votre procédure d'origine pourrait être réécrite comme suit:

create or replace procedure masc (p_amsprogramid varchar2)
as
  cursor c1 
  is
    select   distinct a.mid,
                      b.sid
    from     table_a a
             inner join table_b b on (a.mid = b.mid)
    where    a.aid = p_amsprogramid
    order by mid;

begin
  for rec1 in c1
  loop
    dbms_output.put_line('mid : ' || rec1.mid);
    dbms_output.put_line('sid : ' || rec1.sid);
  end loop;
end masc;
/

Beaucoup plus simple à lire, à comprendre et à maintenir, je pense que vous serez d'accord!

Si vous souhaitez écrire les résultats de la requête SQL sous forme de fichier, vous devez utiliser UTL_FILE au lieu de DBMS_OUTPUT. Gardez à l'esprit que le répertoire dans lequel le fichier est écrit doit être quelque chose qui est monté/mappé sur le serveur sur lequel se trouve la base de données. Si vous écrivez les résultats avec des caractères délimités, vous pourrez alors importer facilement ce fichier dans Excel.

Vous pourriez trouver ceci pour être utile .

0
Boneist

U peut utiliser le curseur de référence à cette fin

            create or replace PROCEDURE MASC (V_AMSPROGRAMID VARCHAR2) AS

            V_MID VARCHAR2(50);
            V_SID VARCHAR2(50);

            C1 sys_refcursor ;
            c2 sys_refcursor ;

            BEGIN

            OPEN C1 for SELECT distinct MID from table_a WHERE AID = V_AID
            ORDER BY MID;

            LOOP

            FETCH C1 INTO V_MID;
            EXIT WHEN C1%NOTFOUND;


            open C2 for SELECT DISTINCT SID INTO V_SID FROM table_b WHERE MID = V_MID;

            LOOP

            FETCH C1 INTO V_MID;
            EXIT WHEN C1%NOTFOUND;

            DBMS_OUTPUT.PUT_LINE('MID : ' || V_MID);
            DBMS_OUTPUT.PUT_LINE('Sid : ' || V_SID);



            END LOOP;

            CLOSE C2;
            CLOSE C1;
            END LOOP;
0
Prabhat Sharma