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

时间:2016-03-09 05:46:50

标签: sql oracle plsql cursor

您好我正在使用以下PLSQL脚本在新表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;
/

现在表cycle_table只包含4行。循环只运行四次,因为它的打印'将记录插入new_table ..'仅4次。

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

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

请建议我该怎么办?我在oracle 10g上使用SQL开发人员

提前致谢

2 个答案:

答案 0 :(得分:1)

这很简单:

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,因为这些资源消耗最少。

答案 1 :(得分:0)

更有效的方法是消除所有循环,并允许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;