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

insertar en... seleccionar... con subconsulta o sin orden de columnas

No, no puede usar una subconsulta para generar la lista de columnas como parte de una instrucción SQL.

Puede generar la declaración completa del diccionario de datos:

select 'insert into cl ("'
  || listagg(column_name, '","') within group (order by column_id)
  || '") select "'
  || listagg(column_name, '","') within group (order by column_id)
  || '" from clt'
from user_tab_columns where table_name = 'CLT';

y luego copie y pegue eso, o use SQL dinámico desde un bloque anónimo:

declare
  stmt varchar2(4000);
begin
  select 'insert into cl ("'
    || listagg(column_name, '","') within group (order by column_id)
    || '") select "'
    || listagg(column_name, '","') within group (order by column_id)
    || '" from clt'
  into stmt
  from user_tab_columns where table_name = 'CLT';

  dbms_output.put_line(stmt); -- to check and debug
  execute immediate stmt;
end;
/

Con un par de tablas ficticias:

create table clt (col1 number, col2 date, col3 varchar2(10));
create table cl (col3 varchar2(10), col1 number, col2 date);

insert into clt (col1, col2, col3) values (42, date '2018-07-12', 'Test');

insert into cl
select * from clt;

SQL Error: ORA-00932: inconsistent datatypes: expected NUMBER got DATE

ejecutar ese bloque da:

insert into cl ("COL1","COL2","COL3") select "COL1","COL2","COL3" from clt

PL/SQL procedure successfully completed.

select * from cl;

COL3             COL1 COL2      
---------- ---------- ----------
Test               42 2018-07-12

También podría convertir ese bloque anónimo en un procedimiento que tome dos nombres de tabla si esto es algo que probablemente quiera hacer con frecuencia (dijiste que tenía que ser reutilizable, pero eso podría significar para las mismas tablas, y podría ser simplemente un bloque en un script).

También puede ir más allá y solo incluir columnas que aparecen en ambas tablas, o verificar que los tipos de datos coincidan exactamente; aunque eso es un poco más de trabajo y puede que no sea necesario.