Oracle
 sql >> Base de données >  >> RDS >> Oracle

Alternative à RETURNING avec INSERT...SELECT

Vous utilisez le insert into ... select from construction. Donc, potentiellement, votre instruction insérera plus d'une ligne, ce qui signifie que votre clause RETURNING renverra plus d'une ligne. Par conséquent, vous devez utiliser la syntaxe BULK COLLECT pour remplir une collection de nouvelles clés.

Alors on essaie quelque chose comme ça...

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;
/

... seulement pour obtenir :

Eh bien ça craint.

Malheureusement, alors que RETURNING BULK COLLECT INTO fonctionne avec les mises à jour et les suppressions, il ne fonctionne pas avec les insertions (ou les fusions viennent à cela). Je suis sûr qu'il y a des raisons très valables dans l'architecture interne du noyau Oracle, mais cela devrait fonctionner, et ce n'est pas très ennuyeux.

Quoi qu'il en soit, comme @PonderStibbons l'a souligné, il existe une solution :la construction FORALL.

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;
/

Voici une démo LiveSQL (connexion OTN gratuite requise) .