(这都是 Oracle 10g):
CREATE OR REPLACE FUNCTION bar(...)
IS
v_first_type VARCHAR2(100) ;
v_second_type VARCHAR2(100);
CURSOR cur IS SELECT a,b FROM source_table ;
v_a int;
v_b char;
BEGIN
OPEN cur;
<<l_next>> --10G doesn't have the continue statement.
LOOP
FETCH cur INTO v_a, v_b ;
EXIT WHEN cur%NOTFOUND ;
--Ignore Record Case: ignore the record entirely
IF a == -1 THEN
-- do something
GOTO l_next ; --10g doesn't have the continue statement.
ELSE
-- do something else
v_first := 'SUCCESS' ;
END IF;
-- Transform Case:
IF b == 'z' THEN
-- do something
v_second := 'something';
ELSE
-- do something
v_second := 'something else';
END IF;
INSERT INTO report_table VALUES (v_first, v_second);
END LOOP;
CLOSE cur;
EXCEPTION
...
END;
我是大学毕业后的第一份工作。我正在查看一些看起来像上面的通用框架的遗留代码(除了它有几百行长并且使用更复杂的处理(不可能有基于集合的解决方案))。
它将许多行从一个表中拉到一个游标中,遍历游标,对其进行转换,并将结果插入到报表中。游标不会插入每条记录——如果记录有问题或者它出于某种原因不喜欢它,它将跳过记录而不插入它(参见 GOTO 语句)。
问题 1:插入在循环内一一发生,而不是在循环外的末尾执行 FORALL。
问题2:游标不使用BULK COLLECT。
最重要的是,有一个存储过程有一个游标,它再次不使用 BULK COLLECT,它在遍历游标中的记录时发出这个函数。在循环的每条记录的末尾发出一个提交。我在这里写的函数中没有提交。
我想重写代码看起来像这样:
CREATE OR REPLACE FUNCTION bar(...)
IS
CURSOR cur IS SELECT a,b FROM source_table ;
TYPE t_source IS TABLE OF cur%ROWTYPE INDEX BY PLS_INTEGER;
TYPE t_report IS TABLE OF destination_table%ROWTYPE INDEX BY PLS_INTEGER;
v_sources t_source;
v_reports t_report
v_report_inx INT := 0; -- To Prevent Sparse Collection
BEGIN
OPEN cur;
<<l_next>> --10G doesn't have the continue statement.
LOOP
FETCH cur BULK COLLECT INTO v_sources LIMIT 100 ;
EXIT WHEN v_sources.count = 0 ;
FOR i IN 1 .. v_sources LOOP
--Ignore Record Case: ignore the record entirely
IF v_sources(i).a == -1 THEN
-- do something
GOTO l_next ; --10g doesn't have the continue statement.
ELSE
-- do something else
v_reports(v_report_inx).first := 'SUCCESS' ;
END IF;
-- Transform Case:
IF v_sources(i).b == 'z' THEN
-- do something
v_reports(v_report_inx).second := 'something';
ELSE
-- do something
v_reports(v_report_inx).second := 'something else';
END IF;
v_report_inx := v_report_inx + 1;
END LOOP;
END LOOP;
FORALL i in 1 .. v_reports.count
INSERT INTO report_table (first, second) VALUES (v_reports(i).first, v_reports(i).v_second);
CLOSE cur;
EXCEPTION
...
END;
重大变化是 1) 使用 BULK COLLECT 到关联数组中,以及 2) 使用 FORALL 出不同的关联数组。
我有两个问题:
1)基于我在第一个片段中提供的框架,我的更改是最优越的方法吗?你会用另一种方式吗?
2) 有什么我没有想到的理由会让人不使用 BULK COLLECT 和 FORALL?也许一些我还没有在遗留代码中实现的复杂处理?该代码最初是在 2002 年形成的(所以我假设是 8i 或 9i),但此后一直在更新。9i 有批量装订。8i 也有批量装订。两者都有关联数组。所以我觉得他们没有使用批量绑定一定是有原因的。