2016-11-02 1 views
0

Ich habe ein Paket:For-Schleife innerhalb des Cursors in plsql

create or replace package body package_name 
as 
procedure 
update_dte 
cursor cur_variable is 
select person_id, eff_start_date, eff_end_date from tab_abc; 

begin 

open cursor cur_variable; 
loop 
num_count := cur_variable%ROWCOUNT; 

for i in 1..num_count 
loop 
fetch cursor cur_variable 
into l_person_id, l_eff_start_date, l_eff_end_date; 

update tab_abc 
set l_eff_start_date='31-dec-4712' 
where person_id=l_person_id; 
end loop; 
end loop; 
close cur_variable; 

end; 
end; 
/

Diese Abfrage, wo ich für Schleife in Cursor-Schleife verwendet haben, wird in Endlosschleife gehen. Grundsätzlich möchte ich durch den Cursor bis zu seiner Zeile zählen, so dass keine Iteration für die Aktualisierung verpasst wird.

+0

Warum verwenden Sie an erster Stelle einen Cursor und eine for-Schleife? Scheint unnötig –

Antwort

0

Der Grund liegt auf der Hand: Sie haben keine Ausgangsbedingung. Außerdem verstehe ich nicht, warum Sie zwei Schleifen benötigen. Dann brauchst du nur die innere Schleife.

eine Exit-Bedingung hinzufügen (Sie die genaue Syntax aber nicht erinnern) so etwas wie:

EXIT WHEN cur_variable%NOT_FOUND ; 

Diese unmittelbar nach dem FETCH sein sollte.

Übrigens müssen Sie die Anzahl der Datensätze nicht überprüfen. Einfach Schleife (für immer) und beenden, wenn keine weiteren Ergebnisse von der FETCH zurückgegeben werden.

+0

Eigentlich ist das Problem, gibt es keine Exit-Anweisung in der äußeren Schleife - der Cursor wird nie abgerufen werden, da 'num_count: = cur_variable% ROWCOUNT;' wird immer 0. – Boneist

+0

Deshalb habe ich Ihnen geschrieben um den Zähler in der Schleife zu entfernen und nur zu überprüfen, ob der Cursor eine END-OF-DATA-Bedingung zurückgibt, um die Schleife zu beenden (die übrigens auch erwähnte, dass Sie in Ihrem Code fehlen). – FDavidov

+0

Ich bin nicht das OP. Aber ich nehme deinen Standpunkt; Ich hatte die Tatsache übersehen, dass die fehlende Exit-Anweisung aus Ihrem ersten Satz nicht mit Ihrer Beispiel-Exit-Anweisung übereinstimmt; mein Schade - Entschuldigung! – Boneist

3

Ihr Code funktioniert nicht wie Sie erwarten, weil a) Sie die Exit-Klausel aus Ihrer äußeren Schleife fehlt, b) bis Sie mindestens Zeile abgerufen haben, wird der% ROWCOUNT 0 zurückgeben (und auch wenn es abgerufen wurde eine Zeile, wenn Sie erwarten, dass die Anzahl der Zeilen im Cursor zurückkehrt, dann irren Sie sich leider - wir wissen nur die Anzahl der Zeilen, die vom Cursor zurückgegeben werden, sobald wir alle Zeilen aus der Zeile abgerufen haben cursor), c) mit l_eff_start_date = '31-dec-4712' versucht man eine Variable als Teil einer update-Anweisung zu setzen - das macht keinen Sinn! - und d) Sie haben die Variablen l_person_id, l_eff_start_date, l_eff_end_date oder num_count nicht deklariert.

Sie haben einige Optionen - zunächst einmal, hier ist das, was Ihr Code aussehen sollte - Sie gar nicht brauchen, dass äußere Schleife:

create or replace package body package_name 
as 
    procedure update_dte 
    is 

    cursor cur_variable is 
    select person_id, eff_start_date, eff_end_date 
    from tab_abc; 

    begin 
    open cursor cur_variable; 
    loop 
     fetch cursor cur_variable 
     into l_person_id, l_eff_start_date, l_eff_end_date; 

     exit when cur_variable%notfound; 

     update tab_abc 
     set start_date = to_date('31-12-4712', 'dd-mm-yyyy') -- assuming start_date is of DATE datatype; 
     where person_id=l_person_id; 
    end loop; 

    close cur_variable; 

    end update_dte; 
end package_name; 
/

Allerdings gibt es einen einfacheren Weg, durch einen Cursor von looping , wo Sie müssen Werte in, Öffnen oder Schließen des Cursors oder das Abrufen der Datensätze keine Sorgen über eine Variable zu schaffen zurückzukehren - den Cursor-for-Schleife das alles für Sie handhaben:

create or replace package body package_name 
as 
    procedure update_dte 
    is 

    cursor cur_variable is 
    select person_id, eff_start_date, eff_end_date 
    from tab_abc; 

    begin 
    for rec in cur_variable; 
    loop 
     update tab_abc 
     set start_date = to_date('31-12-4712', 'dd-mm-yyyy') -- assuming start_date is of DATE datatype; 
     where person_id=l_person_id; 
    end loop; 
    end update_dte; 
end package_name; 
/

jedoch Viel besser und leistungsfähiger ist es, eine einzige update-Anweisung zu verwenden, um das w zu machen Ork auf einen Schlag, anstatt Zeile für Zeile. In Ihrem Fall, Sie brauchen nicht einmal haben Sie den Cursor auf eine Schleife durch, da Sie alle Zeilen in tab_abc aktualisieren, so dass Ihr Update wird einfach:

create or replace package body package_name 
as 
    procedure update_dte 
    is 
    begin 
    update tab_abc 
    set start_date = to_date('31-12-4712', 'dd-mm-yyyy'); -- assuming start_date is of DATE datatype; 
    end update_dte; 
end package_name; 
/

In allen drei Fällen habe ich angenommen, dass Sie haben versucht, die Spalte start_date zu aktualisieren (und sie ist vom Datentyp DATE). Wenn dies nicht der Fall ist, müssen Sie Ihre Frage aktualisieren, um weitere Details zu dem zu erhalten, was Sie mit diesem Verfahren versuchen möchten. Ist es eine Hausaufgabenfrage?

Verwandte Themen