簡體   English   中英

如何使用游標 for 循環在 PL SQL 中將行從一個表插入到另一個表?

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

我不知道這有多少是對的

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;

這是我得到的錯誤

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:

我在這里使用 Scott 模式中的表。

i 是游標記錄,不能直接插入到另一個表中,需要參考具體的列。 例如,

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

您不需要游標(並且不應使用游標,因為循環中的單個插入會更慢並生成更多日志記錄)。 您可以簡單地使用單個INSERT ... SELECT ...語句:

INSERT INTO dept_backup
SELECT * FROM dept;

正如您被告知的那樣,您實際上並不需要 PL/SQL、游標或循環,但是 - 如果您正在學習它們,那么這就是方法。

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>

更短的選項不是顯式聲明游標 - 使用游標 FOR 循環:

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>

請注意,如果使用這樣的語法,則不必關閉游標; 如果您使用以下語法,必須聲明一個游標變量,打開游標,從中獲取,退出循環並關閉游標:

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>

顯然,游標 FOR 循環要簡單得多。

兩個問題(假設deptdept_backup有匹配的列)

  1. 使用此語法時,記錄變量周圍不應有括號
  2. 在循環完成並且已經隱式關閉它之后,您不能顯式關閉 for 循環游標。

嘗試這個:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM