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;
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);
...
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
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 .
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;