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

Alternative zu RETURNING mit INSERT...SELECT

Sie verwenden den Befehl insert into ... select from konstruieren. Ihre Anweisung fügt also möglicherweise mehr als eine Zeile ein, was bedeutet, dass Ihre RETURNING-Klausel mehr als eine Zeile zurückgibt. Folglich müssen Sie die BULK COLLECT-Syntax verwenden, um eine Sammlung zu füllen von neuen Schlüsseln.

Also versuchen wir so etwas ...

declare
    /* NB: define this collection using the appropriate name  */
    type new_keys is table of table_xxx.cola%type;
    col_res new_keys;
begin
    INSERT INTO TBL_XXX
    SELECT COLA * 10, COLB, COLC FROM TBL_YYY
    RETURNING table_xxx.COLA bulk collect INTO COL_RES;
end;
/

... nur um zu bekommen:

Nun, das ist scheiße.

Leider funktioniert RETURNING BULK COLLECT INTO zwar mit Aktualisierungen und Löschungen, aber nicht mit Einfügungen (oder Zusammenführungen). Ich bin mir sicher, dass es sehr gute Gründe in der internen Architektur des Oracle-Kernels gibt, aber das sollte funktionieren, und dass es nicht funktioniert, ist sehr ärgerlich.

Wie auch immer, wie @PonderStibbons darauf hingewiesen hat, gibt es eine Problemumgehung:das FORALL-Konstrukt.

declare
    type new_rows is table of tbl_xxx%rowtype;
    rec_xxx new_rows;
    type new_keys is table of tbl_xxx.cola%type;
    col_xxx new_keys;
begin
    select cola * 10, colb, colc 
    bulk collect into rec_xxx
    from tbl_yyy;

    forall idx in 1 .. rec_xxx.count()
        insert into tbl_xxx
        values rec_xxx(idx)
        returning tbl_xxx.cola bulk collect into col_xxx
    ;

    for idx in 1 .. rec_xxx.count() loop
        dbms_output.put_line('tbl_xxx.cola = ' || col_xxx(idx));
   end loop;
end;
/

Hier ist eine LiveSQL-Demo (kostenlose OTN-Anmeldung erforderlich) .