0

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.

2
  • Avoid for/next loops and individual row processing whenever possible, in any database. They require exponentially more DB kernel interactions and will always, always, always be slow, slow, slow. Always use "set" operations like insert into ... select .... Commented Jul 19, 2022 at 12:21
  • Thank you for your suggestion. I was learning about loops in plsql and I had to do an assignment on it. Will definitely consider your suggestion in the future. Commented Jul 20, 2022 at 2:25

4 Answers 4

1

You do not need a cursor (and should not use one as individual inserts in a loop will be slower and generate a lot more logging). You can simply use a single INSERT ... SELECT ... statement:

INSERT INTO dept_backup
SELECT * FROM dept;
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

i is the cursor record, you cannot insert it directly to another table, you need to refer to the specific columns. For example,

INSERT INTO dept_backup (b_col1, b_col2, b_col3) values(i.c_col1,i.c_col2,i.c_col3);

2 Comments

I tried that and now I'm getting the error as invalid cursor
You dont need this one for looping a cursor: CLOSE cur_depts;
0

Two issues (assuming dept and dept_backup have matching column lists):

  1. there should be no brackets around the record variable when using this syntax.
  2. you cannot explicitly close a for-loop cursor after the loop has completed and already implicitly closed it.

Try this:

declare
    cursor cur_depts is
        select * from dept;
begin
    for r in cur_depts loop
        insert into dept_backup values r;
    end loop;
end;

(I prefer to use r for record loop variables to avoid confusion with i numeric loop variables.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.