Search code examples
sqlfor-loopplsqloracle11g

How can I insert rows from one table to another in PL SQL using the cursor for loop?


I don't know how much of this is right

DECLARE    
    CURSOR cur_depts IS
    SELECT *
    FROM dept;
BEGIN
    FOR i IN cur_depts
    LOOP
       INSERT INTO dept_backup
       VALUES(i);
    END LOOP;
    CLOSE  cur_depts;
END;

And this is the error I got

Error report -
ORA-06550: line 8, column 20:
PL/SQL: ORA-00947: not enough values
ORA-06550: line 8, column 8:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

I'm using the tables from Scott schema here.


Solution

  • As you were told, you don't really need PL/SQL nor cursors nor loops, but - if you're learning about them, then here's how.

    SQL> create table dept_backup as select * From dept where 1 = 2;
    
    Table created.
    
    SQL> declare
      2    cursor cur_depts is
      3      select deptno, dname, loc
      4      from dept;
      5  begin
      6    for i in cur_depts loop
      7      insert into dept_backup (deptno, dname, loc)
      8        values (i.deptno, i.dname, i.loc);
      9    end loop;
     10  end;
     11  /
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from dept_backup;
    
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK
            20 RESEARCH       DALLAS
            30 SALES          CHICAGO
            40 OPERATIONS     BOSTON
    
    SQL>
    

    Even shorter option is not to explicitly declare a cursor - use cursor FOR loop:

    SQL> truncate table dept_backup;
    
    Table truncated.
    
    SQL> begin
      2    for i in (select deptno, dname, loc from dept) loop
      3      insert into dept_backup (deptno, dname, loc)
      4        values (i.deptno, i.dname, i.loc);
      5    end loop;
      6  end;
      7  /
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from dept_backup;
    
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK
            20 RESEARCH       DALLAS
            30 SALES          CHICAGO
            40 OPERATIONS     BOSTON
    
    SQL>
    

    Note that you don't have to close a cursor if you use such a syntax; you would have to declare a cursor variable, open the cursor, fetch from it, exit the loop and close the cursor if you used this syntax:

    SQL> truncate table dept_backup;
    
    Table truncated.
    
    SQL> declare
      2    cursor cur_depts is select deptno, dname, loc from dept;
      3    cd_r   cur_depts%rowtype;
      4  begin
      5    open cur_depts;
      6    loop
      7      fetch cur_depts into cd_r;
      8      exit when cur_depts%notfound;
      9      insert into dept_backup (deptno, dname, loc)
     10        values (cd_r.deptno, cd_r. dname, cd_r.loc);
     11    end loop;
     12    close cur_depts;
     13  end;
     14  /
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from dept_backup;
    
        DEPTNO DNAME          LOC
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK
            20 RESEARCH       DALLAS
            30 SALES          CHICAGO
            40 OPERATIONS     BOSTON
    
    SQL>
    

    Obviously, cursor FOR loop is way simpler.