insert into… select … with subquery or without column order

后端 未结 1 352
灰色年华
灰色年华 2021-01-25 20:21

I\'m using Oracle db and I wonder if it\'s possible to write something like:

INSERT INTO CL (select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME=\'CL\')
SE         


        
相关标签:
1条回答
  • 2021-01-25 21:02

    No, you can't use a subquery to generate the column list as part of an SQL statement.

    You can generate the full statement from the data dictionary:

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

    and then either copy and paste that, or use dynamic SQL from an anonymous block:

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

    With a couple of dummy tables:

    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
    

    running that block gives:

    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
    

    You could also turn that anonymous block into a procedure that takes two table names if this is something you're likely to want to do often (you said it needed to be reusable, but that could mean for the same tables, and could just be a block in a script).

    You could also go further and only include columns that appear in both tables, or verify data types match exactly; though that's a bit more work and may well not be necessary.

    0 讨论(0)
提交回复
热议问题