15

カーソルをフェッチすると、%ROWCOUNT、%ROWTYPE、%FOUND、%NOTFOUND、%ISOPENなどの変数にアクセスできることを知っています。

...しかし、他に使用する理由があるかどうか疑問に思いました

開く-フェッチ-カーソルをループするための命令を閉じる

それよりも

FORサイクルでカーソルをループします...(私の意見では、これは単純であるため、より適切です)

どう思いますか?

4

4 に答える 4

27

パフォーマンスの観点から見ると、その違いは、 OMG Ponies がリンクしている Tim Hall のヒントよりもはるかに複雑です。このヒントは、Web 用に抜粋されたより大きなセクションへの導入であると思います。Tim は、この本のすべてではないにしても、ほとんどの点を述べていると思います。さらに、この議論全体は、使用している Oracle のバージョンによって異なります。これは 10.2、11.1、および 11.2 では正しいと思いますが、古いリリースに戻ると、明らかに違いがあります。

まず第一に、ヒントの特定の例はかなり非現実的です。SELECT INTO ではなく明示カーソルを使用して単一行フェッチをコーディングしている人を見たことがありません。そのため、SELECT INTO がより効率的であるという事実は、実用上の重要性が非常に限られています。ループについて話している場合、関心のあるパフォーマンスは、多くの行をフェッチするのにどれだけコストがかかるかです。そして、そこから複雑さが生じ始めます。

Oracle は、カーソルから PL/SQL コレクションへのデータの BULK COLLECT を実行する機能を 10.1 で導入しました。一度に多くの行をフェッチすることでコンテキストのシフトを最小限に抑えることができるため、これはSQLエンジンからPL/SQLコレクションにデータを取得するためのはるかに効率的な方法です。また、コードを PL/SQL エンジン内にとどめることができるため、これらのコレクションに対する後続の操作がより効率的になります。

ただし、BULK COLLECT 構文を最大限に活用するには、一般に明示カーソルを使用する必要があります。明示カーソルを使用すると、PL/SQL コレクションにデータを入力した後、FORALL 構文を使用してデータをデータベースに書き戻すことができます (カーソルで大量のデータをフェッチしている場合、何らかの操作を行って操作したデータをどこかに保存している可能性が高いという合理的な仮定)。OMG Ponies が正しく指摘しているように、FOR ループで暗黙カーソルを使用すると、Oracle はバックグラウンドで BULK COLLECT を実行して、データのフェッチを低コストにします。ただし、データがコレクションに含まれていないため、コードは行ごとの挿入と更新を遅くします。

一般に、10.2 以降を使用していて、コードがデータを取得してデータベースに書き戻すと仮定すると、

最速

  1. ローカル コレクションへの BULK COLLECT を (適切な LIMIT で) 実行し、FORALL を使用してデータベースに書き戻す明示的なカーソル。
  2. データベースへの単一行の書き込みとともに、バックグラウンドで BULK COLLECT を実行する暗黙のカーソル。
  3. BULK COLLECT を実行せず、PL/SQL コレクションを利用しない明示カーソル。

最も遅い

一方、暗黙カーソルを使用すると、古いコードのリファクタリングや新しい機能の学習に必要な初期費用がほとんどかからずに、一括操作を使用できるという大きなメリットが得られます。PL/SQL 開発のほとんどが、他の言語を主言語とする開発者、または必ずしも新しい言語機能に対応していない開発者によって行われている場合、FOR ループは、新しいBULK COLLECT機能。また、オラクルが将来新しい最適化を導入すると、暗黙のカーソル コードが自動的に利益を得る可能性がはるかに高くなりますが、明示的なコードでは手動での再作業が必要になる可能性があります。

もちろん、パフォーマンスのトラブルシューティングを行って、ループ コードのさまざまなバリアントがどれだけ高速になるかを本当に気にするようになるまでには、多くの場合、より多くのロジックを純粋な SQL に移行することを検討する必要があります。ループコードを完全に捨てます。

于 2010-10-07T21:07:23.970 に答える
7

OPEN / FETCH / CLOSEは、明示カーソル構文と呼ばれます。後者は暗黙カーソル構文と呼ばれます。

すでに気付いた重要な違いの1つは、暗黙カーソルで%FOUND /%NOTFOUND / etcを使用できないことです...もう1つ注意すべき点は、暗黙カーソルは明示カーソルよりも高速であるということです。 100レコード?)明示的なロジックをサポートしていないことに加えて。

追加情報:

于 2010-10-07T20:31:20.967 に答える
3

この2つの実現の重要な違いについては1つを除いて知りません:for ... loopループが終了した後に暗黙的にカーソルを閉じ、open ... fetch ... close構文がカーソルを自分で閉じたい場合(良い方法です)-これは必要ではないと考えました: Oracle は、可視性スコープのアウトバウンド カーソルを自動的に閉じます。また、カーソルでは%FOUNDandを使用できません。%NOTFOUNDfor ... loop

私としては、for ... loop実現がはるかに読みやすく、サポートしやすいと思います。

于 2010-10-07T20:39:28.053 に答える
3

間違っている場合は訂正してください。ただし、どちらにも、他の機能にはない優れた機能が 1 つあります。

for ループを使用すると、次のように実行できます。

for i in (select * from dual)
  dbms_output.put_line('ffffuuu');
end loop;

open .. fetch を使用すると、次のように実行できます。

declare
  cur sys_refcursor;
  tmp dual.dummy%type;
begin
  open cur for 'select dummy from dual';
  loop
    fetch cur into tmp;
    exit when cur%notfound;
    dbms_output.put_line('ffffuuu');
  end loop;
  close cur;
end;

したがって、open fetch では動的カーソルを使用できますが、for ループでは宣言なしで通常のカーソルを定義できます。

于 2010-10-08T17:47:28.867 に答える