如何使用游标在 SQL 中一次插入一行

How to insert one row at a time in SQL using cursor

您好,我正在使用下面的 PLSQL 脚本在新 table new_table.

中插入行
set serveroutput on SIZE 1000000;
DECLARE
CURSOR get_record IS
SELECT * from cycle_table ;
BEGIN
FOR rec IN get_record
LOOP
DBMS_OUTPUT.put_line('Inserting Record into new_table..');
EXECUTE IMMEDIATE('insert into new_table
                  select cycle_code,cycle_instance,cycle_start_date,cycle_end_date
                  from cycle_table');
END LOOP;
COMMIT;
END;
/

现在 table cycle_table 只包含 4 行。该循环仅运行四次,因为它仅打印 'Inserting Record into new_table..' 4 次。

但是当我看到 new_table 它包含 16 行。这意味着每次循环迭代时它都会插入所有 4 行,因此总共 16 行。

我想要的是它一次插入一行。 这样我也可以对该行执行其他操作。就像该行已经存在一样,插入其他一些 table 或任何东西。

请建议我可以在这里做什么?我在 oracle 10g

上使用 SQL 开发人员

提前致谢

很简单:

set serveroutput on SIZE 1000000;
DECLARE
BEGIN
    FOR rec in (select * from cycle_table)
    LOOP
        DBMS_OUTPUT.put_line('Inserting Record into new_table..');
    insert into new_table (cycle_code, 
                           cycle_instance, 
                           cycle_start_date, 
                           cycle_end_date)
                   values (rec.cycle_code, 
                           rec.cycle_instance, 
                           rec.cycle_start_date, 
                           rec.cycle_end_date);

    END LOOP;


    COMMIT;
END;
/

不过,我不鼓励这种方法,因为如果有大量记录,您可能 运行 会出现性能问题。你只有四个,没关系。

我反对的原因是 Oracle 的 PL/SQL 引擎和 SQL 引擎之间涉及上下文切换。我建议您使用 insert into .... select... 或使用 forall,因为这些是资源消耗最少的方法。

一种更有效的方法是消除所有循环,并让 SQL 处理所有事情。这是我的建议:

BEGIN

   -- Handle matches first, because after you handle non-matches, everything matches
   INSERT INTO match_table (cycle_code, cycle_instance, cycle_start_date
                          , cycle_end_date)
      SELECT cycle_table.cycle_code, cycle_table.cycle_instance, cycle_table.cycle_start_date
           , cycle_table.cycle_end_date
        FROM cycle_table INNER JOIN new_table ON (new_table.cycle_code = cycle_table.cycle_code);

   -- Single insert to insert all non matching records
   INSERT INTO new_table (cycle_code, cycle_instance, cycle_start_date
                        , cycle_end_date)
      SELECT cycle_code, cycle_instance, cycle_start_date
           , cycle_end_date
        FROM cycle_table
       WHERE NOT EXISTS
                (SELECT NULL
                   FROM new_table
                  WHERE new_table.cycle_code = cycle_table.cycle_code);

   COMMIT;
END;