2017-04-20 4 views
0

Mein Verständnis ist OUT formale Parameter sollten immer auf NULL, wenn die Prozedur aufgerufen wird.Oracle out Parameter nicht NULL

parameter_tests.getstring würde erwarten, "Parameter null" beide Male um die Anruferproc-Schleife auszugeben. Und wenn Sie den Code ausführen, passiert genau das.

Die Ausgabe von parameter_tests.getcursor zeigt jedoch an, dass der Referenzcursor zum zweiten Mal in der Schleife geöffnet ist.

Wenn der Formalparameter p_out beim Aufruf von getcursor auf Null gesetzt wurde, würden wir erwarten, dass der Referenzcursor geschlossen wird. Stattdessen übergibt es den offenen Referenzcursor und es ist eigentlich die OPEN FOR, die den offenen Referenzcursor aufräumt (und verhindert, dass wir die maximal offenen Cursor treffen, wenn Sie hunderte von Wiederholungen durchführen).

Wenn ich manuell den Referenzcursor zwischen Aufrufen auf Null setzt, verhält es sich wie erwartet.

Kann mir jemand sagen, warum Referenz-Cursor als Sonderfall behandelt werden, wenn sie OUT-Parameter sind? Und welche anderen Arten werden anders behandelt?

Die Datenbankversion ist 11.2.0.2.0.

Antwort

1

According to the documentation:

Wenn ein Cursor-Variable als der formale Parameter eines Unterprogramm erklärt:

  • Wenn das Unterprogramm öffnet oder ordnet einen Wert an das Cursor-Variable, dann wird der Parameter-Modus sein muss IN HERAUS.
  • Wenn das Unterprogramm nur die Cursorvariable abruft oder schließt, kann der Parametermodus entweder IN oder IN OUT sein.

Der Cursor Parameter scheint behandelt zu werden, als ob es wie IN OUT erklärt worden war, obwohl man eigentlich nur als OUT erklären. Das Verhalten ist das, was Sie von IN OUT erwarten würden; Sie können den Cursor im zweiten Aufruf sogar abrufen und den Dummy-Wert von Dual sehen.

Es macht Sinn, wenn man die Art des Ref-Cursors als Zeiger betrachtet, aber Sie würden denken, dass die Regel durch das Compiler-Error erzwungen wird, wenn nur OUT angegeben wurde (und nicht einmal als Warnung gemeldet wird). . Das Beispiel in der Dokumentation funktioniert übrigens auch nur mit OUT.

So sieht das wirklich wie ein Compiler-Fehler aus, da es die falsche Parameterrichtung nicht meldet; aber auch (mehr dürftig!) ein Fehler in Ihrem Code, weil er nicht als IN OUT deklariert ist. Und möglicherweise ein weiterer Fehler, weil Sie nicht schließen explizit die Cursor - die auf ‚fix‘ erscheinen auch die Frage, Art:

procedure callerproc is 
    lv_cursor sys_refcursor; 
    lv_string varchar2(20) := null; 
begin 
    for i in 1..2 loop 
    getstring(lv_string); 

    getcursor(lv_cursor); 

    close lv_cursor; 
    end loop; 

end callerproc; 

, die als Zuweisung null an das Cursor-Variable wahrscheinlich mehr korrekt ist , was du erwähnt hast, funktioniert auch.

+0

Große Antwort. Vielen Dank. Sie haben recht, wenn explizites Schließen die beste Wahl ist. Die Quelle der Frage untersuchte tatsächlich ein Problem mit nicht geschlossenen Cursorn und wir fanden heraus, dass wir die Cursorgrenze nicht überschreiten konnten, indem wir sie in einer Schleife öffneten. –