はい、多くの人が悪い習慣に従っています。
悪いスタイル
OPEN/FETCH/CLOSE が完全に不要なコードを追加するという @Osy に同意します。さらに言えば、 はほとんど使用すべきではありませんCURSOR
。
まず第一に、通常はプレーン SQL で可能な限り多くのことを行いたいと考えます。PL/SQL を使用する必要がある場合は、暗黙カーソルを使用してください。コードの行を節約し、関連するロジックをより近くに保つのに役立ちます。
私は、個々のコード単位をできるだけ小さく保つことを強く信じています。一見すると、これを行うのCURSOR
に役立つように思えます。SQL を 1 か所で定義し、後で PL/SQL ループを実行できます。
しかし、実際には、その余分な間接的な層はほとんど価値がありません。多くのロジックが SQL にある場合もあれば、多くのロジックが PL/SQL にある場合もあります。しかし実際には、両方に多くの複雑なロジックを配置することはほとんど意味がありません。コードは通常、次のいずれかのようになります。
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
また:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
いずれにしても、コード セクションの 1 つが非常に小さくなります。コードのこれら 2 つのセクションを分離することの複雑さは、より大きな単一のコード セクションの複雑さよりも大きくなります。(しかし、それは明らかに私の意見です。)
悪いパフォーマンス
OPEN/FETCH/CLOSE を使用すると、パフォーマンスに重大な影響があります。この方法は、カーソル for ループまたは暗黙カーソルを使用するよりもはるかに遅くなります。
コンパイラは、一部の for ループで一括収集を自動的に使用できます。ただし、Oracle のプレゼンテーション「PL/SQL Performance—Debunking the Myths」の 122 ページから引用すると、次のようになります。
オープン、フェッチ ループ、クローズ フォームを使用して、このチャンスを無駄にしないでください。
簡単な例を次に示します。
--Sample data
create table t(a number, b number);
insert into t select level, level from dual connect by level <= 100000;
commit;
--OPEN/FETCH/CLOSE
--1.5 seconds
declare
cursor test_cur is
select a, b from t;
test_rec test_cur%rowtype;
counter number;
begin
open test_cur;
loop
fetch test_cur into test_rec;
exit when test_cur%notfound;
counter := counter + 1;
end loop;
close test_cur;
end;
/
--Implicit cursor
--0.2 seconds
declare
counter number;
begin
for test_rec in (select a, b from t) loop
counter := counter + 1;
end loop;
end;
/