2009-05-03 3 views
1

Ich habe eine folgende Oracle-Prozedur gespeichertWie funktionieren Orakel gespeicherte Prozeduren (w/cursors)?

CREATE OR REPLACE 
PROCEDURE getRejectedReasons 
    (
    p_cursor IN OUT SYS_REFCURSOR) 
AS 
BEGIN 
    OPEN p_cursor FOR SELECT * FROM reasons_for_rejection; 
END; 

Allerdings, wenn ich diese gespeicherte Prozedur in SQL-Entwickler laufen dann nicht, daß ich nichts sehen. Ich sehe gerade, etwa so:

Connecting to the database oracleLocal. 
Process exited. 
Disconnecting from the database oracleLocal. 

ich von MS SQL Server komme und bin es gewohnt, mit den tatsächlichen Ergebnissen zu sehen, wenn eine gespeicherte Prozedur wie folgt ausgeführt werden. Gibt diese gespeicherte Prozedur keine Ergebnisse zurück, weil ich einen Cursor verwende?

Antwort

1

Sie haben den Cursor geöffnet. Sie haben nichts davon ausgewählt, aktualisiert oder weiterentwickelt.

Alle öffnen, effektiv, um die übereinstimmenden Zeilen in temporären Speicher auswählen, so können Sie den Cursor Zeile für Zeile weiterleiten. Was du nicht getan hast.

+0

Wie kann ich ‚Fortschritt‘ der Cursor, so würde es mir die Ergebnisse zeigen, wenn ich es ausführe. –

+0

Nun, Sie nicht. Das heißt, der ganze Punkt eines Cursors besteht darin, eine Zeile zu einer Zeit zu führen, nicht eine ganze Ergebnismenge von vielen Zeilen. Sie können die Schleife mit 'for rec in p_cursor loop' 'end loop;' – tpdi

+0

ok, ich werde diese gespeicherte Prozedur in einer iBatis-Datei mit Java-Code verwenden. Also ich denke, da kann ich den ganzen Cursor bekommen und dann darüber hinwegschleifen –

0

Einer der Unterschiede zwischen Oracle und SQL Server besteht darin, dass Letzterer natürlich Ergebnismengen zurückgibt. Ich würde übrigens eine Funktion verwenden.

In Oracle geben Funktionen normalerweise ein einzelnes Element zurück. Cursor kamen später.

Es gibt einige Online-Dokumentationen, die Ihnen helfen werden, die Verwendung von Refcursor-Bind-Variablen zu verstehen. Hier ist eine solche für SQL * Plus:

http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1122

ich in SQL Developer denken können Sie die gleiche Sache mit autoprint tun auf, obwohl ich nicht getestet haben.

ein Blog gefunden, die etwas bespricht auch ähnlich:

http://vadimtropashko.wordpress.com/cursors/

+0

Ein pl/sql-Cursor ist ein einzelnes Element, eine pl/sql-Funktion kann einen Cursor zurückgeben. – tuinstoel

-1

ETA: Ok. Ignoriere, was ich geschrieben habe. Höre auf jemand anderen. Anscheinend ist es falsch, als ich unten gewählt wurde.

Was tpdi sagte, ist richtig. Sie müssen etwas mit dem Cursor tun, nachdem Sie es deklariert haben.

Hier ist ein Beispiel mit zwei Cursor in verschachtelten Schleifen

PROCEDURE update_insert_tree (exid_in IN NUMBER, outvar_out OUT VARCHAR2) 
    IS 
     nxtid   NUMBER; 
     phaseid  NUMBER; 
     rowcounter1 NUMBER; 
    BEGIN 
     rowcounter1 := 0; 
     outvar_out := 0; 

     FOR acur IN (SELECT dept_exercise_id, phase 
        FROM ep_dept_exercise 
        WHERE exercise_id = exid_in) 
     LOOP 

     <<dept_loop>> 
     FOR thecur IN (SELECT document_name, thelevel, sortnum, type_flag, 
           ex_save_id 
          FROM ep_exercise_save 
         WHERE exercise_id = exid_in) 
     LOOP 
      phaseid := acur.phase; 

      IF phaseid = 0 
      THEN 
       phaseid := 10; 

       UPDATE ep_dept_exercise 
        SET phase = 10 
       WHERE dept_exercise_id = acur.dept_exercise_id; 
      END IF; 

      <<doc_loop>> 
5

Die gespeicherte Prozedur etwas Rückkehr wird es nur Sie tun nichts mit den Ergebnissen.

Sie können dies tun, indem einfach das folgende Skript in sqldeveloper ausgeführt wird:


VARIABLE csr REFCURSOR; 
EXEC getRejectedReasons(:csr); -- the colon identifies the parameter as a variable 
PRINT csr; 

Eine andere Methode ist es, jede Zeile zu holen und eine Art der Verarbeitung zu tun:


DECLARE 
    -- sys_refcursor is weakly typed 
    refcsr SYS_REFCURSOR; 
    -- define a record so we can reference the fields 
    rej_rec Reasons_for_Rejection%ROWTYPE; 
BEGIN 

    getRejectedReasons(refcsr); 

    -- loop through the results 
    LOOP 
     -- gets one row at a time 
     FETCH refcsr INTO rej_rec; 
     -- if the fetch doesn't find any more rows exit the loop 
     EXIT WHEN refcsr%NOTFOUND; 
     -- Do something here. 
     -- For example : DBMS_OUTPUT.PUT_LINE(rej_rec.reason_desc); 
    END LOOP; 

END;