Use Oracle for all to see what kinds of insert s are available

Keywords: SQL

Environment: 11g

create table emp_copy
as
select empno, ename, job, hiredate from emp where 1 = 2;  

1.Whole
--Abbreviation
declare
     cursor c_emps is
        select empno, ename, job, hiredate from emp;
     type emp_aat is table of c_emps%rowtype
        index by pls_integer;
     aa_emps emp_aat;

  begin
     open c_emps;
     fetch c_emps bulk collect into aa_emps;
     close c_emps;

     forall i in  1 .. aa_emps.count
        insert /*+ append_values*/ into emp_copy
        values  aa_emps(i);
     dbms_output.put_line(
        to_char(sql%rowcount) || ' rows inserted.'
        );
  end;

//Equivalent to: (specify field)
declare
     cursor c_emps is
        select empno, ename, job, hiredate from emp;
     type emp_aat is table of c_emps%rowtype  ;
       
     aa_emps emp_aat;

  begin
     open c_emps;
     fetch c_emps bulk collect into aa_emps;
     close c_emps;

     forall i in  1 .. aa_emps.count
       insert /*+ append_values*/ into emp_copy
          (empno, ename, job, hiredate)
        values
          (aa_emps(i).empno,
           aa_emps(i).ename,
           aa_emps(i).job,
           aa_emps(i).hiredate);
  end;
  //Support append ﹣ values


2.Specified field,indices of You can skip values that don't exist
create table emp_copy
  as
  select empno, ename, job, hiredate from emp where 1 = 2;  
  
  select * from emp_copy;
  
  declare
     cursor c_emps is
        select empno, ename, job, hiredate from emp;
     type emp_aat is table of c_emps%rowtype
        index by pls_integer;
     aa_emps emp_aat;

  begin
     /* bulk fetch sample data... */
     open c_emps;
     fetch c_emps bulk collect into aa_emps;
     close c_emps;
     
     forall i in indices of aa_emps
        insert into emp_copy
          (empno, ename, job, hiredate)
        values
          (aa_emps(i).empno,
           aa_emps(i).ename,
           aa_emps(i).job,
           aa_emps(i).hiredate);

     dbms_output.put_line(
        to_char(sql%rowcount) || ' rows inserted.'
        );
  end;
//In the same way, support / * + append [values * / / / actual measurement


3.Specified field,Usage dynamics sql
declare
     cursor c_emps is
     select empno, ename, job, hiredate from emp;
     --Not used here index by pls_integer Same effect;
     type emp_aat is table of c_emps%rowtype   index by pls_integer;
     aa_emps emp_aat;
     --dynamic sql Same support append_values
     v_sql varchar2(20000):='insert /*+ append_values*/ into emp_copy (empno, ename, job, hiredate) values(:1,:2,:3,:4)';

  begin
     open c_emps;
     fetch c_emps bulk collect into aa_emps;
     close c_emps;
     forall i in  1 .. aa_emps.count
        execute immediate v_sql using  aa_emps(i).empno,
                                       aa_emps(i).ename,
                                       aa_emps(i).job,
                                       aa_emps(i).hiredate;
  end;

//Support append ﹣ values;


4.forall Also support insert into..select mode,Field insertion can be specified
//But the append method is not supported
//The effect of append and append [values] is the same;
insert /*+append_values*/ into emp_copy
select empno, ename, job, hiredate  from emp where rowid='AAAUVnAAEAAAiOHAAB';


//Method 1: one time submission
declare
  cursor c_emps is
    select rowid rid from emp;
  v_tab dbms_sql.Urowid_Table;

begin
  open c_emps;
  fetch c_emps bulk collect
    into v_tab;
  close c_emps;

  forall i in 1 .. v_tab.count
    insert 
    into emp_copy
      select empno, ename, job, hiredate from emp where rowid = v_tab(i);          
  dbms_output.put_line(sql%rowcount || ' rows inserted.');  
  commit; --Put on sql%rowcount behind,Otherwise, you will not get the number of lines
end;


//Mode 2: batch submission, relatively complete writing
declare
  cursor c_emps is
    select rowid rid from emp;
  v_tab   dbms_sql.Urowid_Table;
  v_limit pls_integer := 5;
  v_count pls_integer:=0;
begin
  open c_emps;

  loop
    v_count:=v_count+1;
    fetch c_emps bulk collect
      into v_tab limit v_limit;   
      
    forall i in 1 .. v_tab.count
      insert 
      into emp_copy
        select empno, ename, job, hiredate from emp where rowid = v_tab(i);     
    dbms_output.put_line('The first'||v_count||'Secondary cycle:'||(sql%rowcount) || ' rows inserted.'); 
    commit;
    exit when c_emps%notfound;
  end loop;   
  close c_emps;   
  
exception when
  others then
  dbms_output.put_line(sqlerrm||dbms_utility.format_error_backtrace);
end;

//Output:
//The first cycle: 5 rows inserted
//The second cycle: 5 rows inserted
//The third cycle: 2 rows inserted


//Update and delete can be done in the same way as above

Summary:
For the efficiency of insert operation, the priority is cats, followed by merge into + append [values
If the memory is insufficient, batch submit + append ﹣ values is used;
For batch submissions:
If the values in the set are not continuous, use indexes of;
If you want to Insert into values continuously, you can,
The fourth method does not support append, and it is checked twice. The efficiency is not good, and it is not recommended;
If the sql to be queried is dynamic, use dynamic sql;

For update operation efficiency:
rowid is the most efficient, but the operation is a little bit cumbersome
Then manually query rowid and batch update or merge into
Then automatic task DBMS? Parallel? Execute

If anything is wrong, please correct it. Thank you
Q:279907389

Posted by camdagr81 on Sun, 29 Dec 2019 08:39:01 -0800