我是 PL/SQL 新手。 我有一个类似的程序:
create or replace procedure insert_charge is
v_count number;
begin
for i in (select t.name, t.hire_date, t.salary
from emp t
where t.create_date >= (sysdate - 30)
and t.salary = 0) loop
insert into charge
(name, hire_date, salary)
values
(i.name, hire_date, salary);
commit;
update emp l
set l.status = 1
where l.name = i.name
and l.status = 0
and l.hire_date = i.hire_date;
commit;
end loop;
exception
when others then
rollback;
end insert_charge;
如何使用FORALL语句来代替这个?
FORALL
还有一些额外的任务;即定义一个集合来定义大块区域,并定义该集合类型的变量来包含实际数据。作为安全值,您应该对一次获取的数量设置限制。 Bulk Collect/Forall 是速度与内存的权衡。并且在某个点(取决于您的配置)收益递减。除了您使用的内存之外,数据库中的其他进程也无法使用它。与您的其他查询很好地吻合。然后正如 @Littlefoot 指出的那样,不要压制异常,记录它们并重新加注。最后,关于提交的注释。 **不要在每个 DML 语句之后提交,您可能需要花一些时间来调查[事务][1]。考虑到这一点,你的程序就变成了这样:
create or replace procedure insert_charge is
cursor c_emp_cur is
select t.name, t.hire_date, t.salary
from emp t
where t.create_date >= (sysdate - 30)
and t.salary = 0;
type c_emp_array_t is table of c_emp%rowtype ; -- define collection for rows selected
k_emp_rows_max constant integer := 500; -- defines the maximum rows per fetch
l_emp_list c_emp_array_t; -- define variable of rows collection
begin
open c_emp_cur;
loop
fetch c_emp_cur -- fetch up to LIMIT rows from cursor
bulk collect
into l_emp_collect
limit k_emp_rows_max;
forall i in 1 .. l_emp_collect.count -- run insert for ALL rows in the collection
insert into charge(name, hire_date, salary)
values( l_emp_collect(i).name
, l_emp_collect(i).hire_date
, l_emp_collect(i).salary);
forall i in 1 .. l_emp_collect.count -- run update for ALL rows in the collection
update emp l
set l.status = 1
where l.name = l_emp_collect(i).name
and l.status = 0
and l.hire_date = l_emp_collect(i).hire_date;
exit when c_emp_cur%notfound; -- no more rows so exit
end loop;
close c_emp_cur;
commit; -- JUST 1 COMMIT;
exception
when others then
generate_exception_log ('insert_charge', sysdate, sql_errm ); --ASSUMED Anonomous Transaction procedure for exception log table.
raise;
end insert_charge;
免责声明:未经测试。 [1]:https://www.techopedia.com/definition/16455/transaction-databases
你不能。
FORALL 语句运行一个 DML 语句多次
ONE DML 语句。您有两个(更新和插入)。
截至您编写的代码:
COMMIT
移出循环when others
“处理程序”,因为它不处理任何内容。如果发生错误,Oracle 将默默回滚并报告过程成功完成,而实际上 - 失败el forall con 更新 tiene 错误:
LS-00436:实现限制:无法引用 BULK In-BIND 记录表的字段 ORA-06550: 第 21 行,第 43 列: PLS-00382:表达式类型错误 ORA-06550: 第 20 行,第 43 列: PLS-00436:实现限制:无法引用 BULK In-BIND 记录表的字段 ORA-06550: 第 20 行,第 43 列: PLS-00382:表达式类型错误 ORA-06550: 第 19 行,第 43 列: PLS-00436:实现限制:无法引用 BULK In-BIND 记录表的字段 ORA-06550: 第 19 行,第 43 列: PLS-00382:表达式类型错误 ORA-06550: 第 18 行,第 43 列: PLS-00436:实现限制:无法引用 BULK In-BIND 记录表的字段 ORA-06550: 第 18 行,第 43 列: PLS-00382:表达式类型错误 ORA-06550: 第 17 行,第 43 列: PLS-00436:实现限制:无法引用 BULK In-BIND 记录表的字段 ORA-06550: 第 17 行,第 43 列: PLS-00382:表达式为