Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Alternativa para RETURNING com INSERT...SELECT


Você está usando o insert into ... select from construir. Portanto, potencialmente, sua instrução inserirá mais de uma linha, o que significa que sua cláusula RETURNING retornará mais de uma linha. Consequentemente, você precisa usar a sintaxe BULK COLLECT para preencher uma coleção de novas chaves.

Então tentamos algo assim...
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;
/

... apenas para obter:

Bem, isso é péssimo.

Infelizmente, embora RETURNING BULK COLLECT INTO funcione com atualizações e exclusões, ele não funciona com inserções (ou mesclagens). Tenho certeza de que existem razões muito sólidas na arquitetura interna do kernel do Oracle, mas isso deve funcionar, e isso não é muito irritante.

De qualquer forma, como @PonderStibbons apontou, existe uma solução alternativa:a construção 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;
/

Aqui está uma demonstração do LiveSQL (requer login OTN gratuito) .