sql >> Base de Datos >  >> RDS >> Oracle

Alternativa a VOLVER con INSERTAR... SELECCIONAR

Estás usando insert into ... select from construir. Entonces, potencialmente, su declaración insertará más de una fila, lo que significa que su cláusula RETURNING devolverá más de una fila. En consecuencia, debe usar la sintaxis BULK COLLECT para completar una colección de llaves nuevas.

Así que intentamos algo como esto...

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

... solo para obtener:

Bueno, eso apesta.

Desafortunadamente, mientras que RETURNING BULK COLLECT INTO funciona con actualizaciones y eliminaciones, no funciona con inserciones (o fusiones). Estoy seguro de que hay razones muy sólidas en la arquitectura interna del kernel de Oracle, pero esto debería funcionar, y que no sea así es muy molesto.

De todos modos, como señaló @PonderStibbons, hay una solución alternativa:la construcción 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;
/

Aquí hay una demostración de LiveSQL (se requiere inicio de sesión OTN gratuito) .