Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle-Funktion und Cursor mit dynamischem Tabellennamen

  • Es besteht keine Notwendigkeit, einen c1 zu deklarieren type für einen schwach typisierten Ref-Cursor. Sie können einfach den SYS_REFCURSOR verwenden Typ.
  • Sie können auf diese Weise implizite und explizite Cursoraufrufe nicht mischen. Wenn Sie zu OPEN gehen B. ein Cursor, müssen Sie FETCH ausführen davon in einer Schleife und Sie müssen CLOSE es. Sie können nicht OPEN und CLOSE es, aber dann in einer impliziten Cursor-Schleife daraus abrufen.
  • Sie müssen eine Variable (oder Variablen) deklarieren, in die die Daten geholt werden. Ich habe einen Datensatztyp und eine Instanz dieses Datensatzes deklariert, aber Sie könnten genauso gut zwei lokale Variablen und FETCH deklarieren in diese Variablen.
  • ROWID ist ein reserviertes Wort, also habe ich ROWPOS verwendet stattdessen.

Wenn Sie das zusammensetzen, können Sie so etwas schreiben wie

SQL> ed
Wrote file afiedt.buf

  1  CREATE OR REPLACE Function Findposition (
  2      model_in IN varchar2,
  3      model_id IN number)
  4    RETURN number
  5  IS
  6    cnumber number;
  7    c2      sys_refcursor;
  8    type result_rec is record (
  9      id      number,
 10      rowpos  number
 11    );
 12    l_result_rec result_rec;
 13  BEGIN
 14    open c2 FOR 'SELECT id,ROW_NUMBER() OVER ( ORDER BY id) AS rowpos FROM '||model_in;
 15    loop
 16      fetch c2 into l_result_rec;
 17      exit when c2%notfound;
 18      IF l_result_rec.id=model_id
 19      then
 20        cnumber :=l_result_rec.rowpos;
 21      end if;
 22    END LOOP;
 23    close c2;
 24    RETURN cnumber;
 25* END;
SQL> /

Function created.

Ich glaube, dies gibt das erwartete Ergebnis zurück

SQL> create table foo( id number );

Table created.

SQL> insert into foo
  2    select level * 2
  3      from dual
  4   connect by level <= 10;

10 rows created.

SQL> select findposition( 'FOO', 8 )
  2    from dual;

FINDPOSITION('FOO',8)
---------------------
                    4

Beachten Sie, dass es aus Effizienzgründen viel besser wäre, dies als einzelne SQL-Anweisung zu schreiben, anstatt einen Cursor zu öffnen und jedes Mal jede Zeile aus der Tabelle abzurufen. Wenn Sie entschlossen sind, einen Cursor zu verwenden, sollten Sie den Cursor verlassen, wenn Sie die gewünschte Zeile gefunden haben, anstatt weiterhin jede Zeile aus der Tabelle abzurufen.

Aus Sicht der Code-Klarheit erscheinen viele Ihrer Variablennamen und Datentypen ziemlich seltsam. Ihre Parameternamen scheinen schlecht gewählt zu sein - ich würde model_in nicht erwarten B. der Name der Eingabetabelle sein. Deklarieren eines Cursors namens c2 ist ebenfalls problematisch, da es sehr wenig beschreibend ist.