3

其中哪个性能更高。

版本 1使用Cursor For Loop

DECLARE
  total_val number(6);

  CURSOR c1 IS
  SELECT * FROM emp
  ;
BEGIN
  total_val := 0;
  FOR emp_rec IN c1
  LOOP
    total_val := total_val + emp_rec.sal;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
END;

版本 2首先用于Bulk Collect将所有行放入 PLSQL 集合,然后对其进行迭代。

DECLARE
  total_val number(6);

  CURSOR c1 IS
  SELECT * FROM emp
  ;

  TYPE emp_recs_type IS TABLE OF emp%ROWTYPE;
  emp_recs emp_recs_type;
BEGIN
  total_val := 0;

  OPEN c1;
  FETCH c1 BULK COLLECT INTO emp_recs;
  CLOSE c1;

  FOR l_index IN emp_recs.FIRST..emp_recs.LAST
  LOOP
    total_val := total_val + emp_recs(l_index).sal;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
END;

请假设Cursor可能返回许多行,可能是成千上万或更多。

4

1 回答 1

2

找出答案的最好方法是真正建立一个实验并尝试一下。

当然,对于您的示例,最好的代码是:

DECLARE
  total_val number(6);
BEGIN
  SELECT SUM(sal) INTO total_val FROM emp;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
END;

但是,我意识到这只是一个简单的例子!

理论上使用 BULK COLLECT 应该会更好,但实际上这些天(肯定是在 11G 中)Oracle 默默地在幕后批量提取 100 行的批次 - 请参阅这个 AskTom 线程

如果您自己使用 BULK COLLECT 并且可能存在未指定的行数,您应该使用 LIMIT 子句,否则您可能会遇到内存问题。对于您的示例,这将类似于:

DECLARE
  total_val number(6);

  CURSOR c1 IS
  SELECT * FROM emp
  ;

  TYPE emp_recs_type IS TABLE OF emp%ROWTYPE;
  emp_recs emp_recs_type;
BEGIN
  total_val := 0;

  OPEN c1;

  LOOP
    FETCH c1 BULK COLLECT INTO emp_recs LIMIT 100;

    EXIT WHEN c1.COUNT = 0;

    FOR l_index IN emp_recs.FIRST..emp_recs.LAST
    LOOP
      total_val := total_val + emp_recs(l_index).sal;
    END LOOP;

  END LOOP;

  DBMS_OUTPUT.PUT_LINE('TOTAL SALARIES: ' || total_val);
  CLOSE c1;
END;
于 2013-10-03T10:17:52.760 回答