如何在 PL/SQL 中使用 BULK COLLECT 和 FORALL 替换 CURSOR FOR LOOP?
Posted
技术标签:
【中文标题】如何在 PL/SQL 中使用 BULK COLLECT 和 FORALL 替换 CURSOR FOR LOOP?【英文标题】:How to use BULK COLLECT and FORALL to replace CURSOR FOR LOOP in PL/SQL? 【发布时间】:2014-09-23 16:25:10 【问题描述】:PL/SQL 中如何使用 BULK COLLECT 和 FORALL 代替 CURSOR FOR LOOP?我希望有一种更有效的方式来更新单个表中的记录。
假设我有以下 PL/SQL 代码:
DECLARE
var_buy_more_shoes inventory.buy_more_shoes%TYPE := NULL;
var_buy_more_bananas inventory.buy_more_bananas%TYPE := NULL;
var_buy_more_iphone6s inventory.buy_more_iphone6s%TYPE := NULL;
CURSOR cur
IS
SELECT *
FROM inventory
FOR UPDATE;
BEGIN
FOR rec IN cur
LOOP
IF rec.pair_of_shoes_left <= 100
THEN
var_buy_more_shoes := 'Yes';
END IF;
IF rec.weight_of_bananas_left <= 200
THEN
var_buy_more_bananas := 'Yes';
END IF;
IF rec.number_of_iphone6s_left <= 50
THEN
var_buy_more_iphone6s := 'Yes';
END IF;
UPDATE inventory a
SET A.buy_more_shoes = var_buy_more_shoes,
A.buy_more_bananas = var_buy_more_bananas,
A.buy_more_iphone6s = var_buy_more_iphone6s
WHERE CURRENT OF cur;
END LOOP;
COMMIT;
END;
谢谢。
【问题讨论】:
【参考方案1】:这可以在单个更新语句中完成:
UPDATE inventory
SET buy_more_shoes = CASE
WHEN pair_of_shoes_left <= 100 THEN 'Yes'
ELSE NULL
END
, buy_more_bananas = CASE
WHEN weight_of_bananas_left <= 200 THEN 'Yes'
ELSE NULL
END
, buy_more_iphone6s = CASE
WHEN number_of_iphone6s_left <= 50 THEN 'Yes'
ELSE NULL
END
【讨论】:
【参考方案2】:您可以创建表对象和集合,然后将查询结果批量收集到表集合中。
CREATE OR REPLACE EDITIONABLE TYPE "F_OBJ" AS OBJECT (
Employer_name VARCHAR2(100),
Employer_id VARCHAR2 ( 100 ))
CREATE OR REPLACE EDITIONABLE TYPE "F_TAB" as table of _OBJ
create or replace function "fname"
return f_tab
is
l_f_tab f_tab;
begin
SELECT f_obj(employee_name, employee_id) bulk collect into f_tab from employee_table
return f_tab;
【讨论】:
以上是关于如何在 PL/SQL 中使用 BULK COLLECT 和 FORALL 替换 CURSOR FOR LOOP?的主要内容,如果未能解决你的问题,请参考以下文章
带有 BULK COLLECT 的 Oracle PL/SQL 6504
为啥 PL/SQL Bulk DML 对具有父子约束表的大型数据集运行缓慢?