如何使用游标在 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;
您好,我正在使用下面的 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;