web-dev-qa-db-ja.com

Oracleの明示的カーソルと暗黙的カーソルの違いは何ですか?

PL/SQLのカーソルの用語に少しさびています。誰もがこれを知っていますか?

25
Brian G

暗黙カーソルとは、問合せの実行時にOracleによって「自動的に」作成されるカーソルです。コーディングは簡単ですが、問題があります

  • 非効率(ANSI標準では、複数のレコードがあるかどうかを確認するために2回フェッチする必要があると規定されています)
  • データエラーに対する脆弱性(2行取得した場合、TOO_MANY_ROWS例外が発生します)

SELECT col INTO var FROM table WHERE something;

明示カーソルとは、自分で作成するカーソルです。それはより多くのコードを必要としますが、より多くの制御を与えます-たとえば、最初のレコードだけが必要で、他のレコードがあるかどうかは気にしない場合は、open-fetch-closeすることができます。

DECLARE   
  CURSOR cur IS SELECT col FROM table WHERE something; 
BEGIN
  OPEN cur;
  FETCH cur INTO var;
  CLOSE cur;
END;
40
Sten Vesterli

明示的なカーソルは、宣言ブロックでそのように定義されています。

DECLARE 
CURSOR cur IS 
  SELECT columns FROM table WHERE condition;
BEGIN
...

暗黙カーソルはコードブロックに直接含まれています。

...
BEGIN
   SELECT columns INTO variables FROM table where condition;
END;
...
17
stjohnroe

1.CURSOR:PLSQLがSQL文を発行すると、SQL文を解析および実行するためのプライベート作業領域が作成され、カーソルと呼ばれます。

2.IMPLICIT:PL/SQL実行可能ブロックがSQL文を発行する場合。 PL/SQLは暗黙的なカーソルを作成し、自動的に管理することで暗黙的なオープンとクローズが行われます。 sqlステートメントが1行のみを返す場合に使用します。4つの属性SQL%ROWCOUNT、SQL%FOUND、SQL%NOTFOUND、SQL%ISOPENがあります。

3.EXPLICIT:プログラマーによって作成および管理されます。明示的なオープン、フェッチ、クローズのたびに必要です。 sqlステートメントが複数の行を返す場合に使用されます。また、4つの属性CUR_NAME%ROWCOUNT、CUR_NAME%FOUND、CUR_NAME%NOTFOUND、CUR_NAME%ISOPENがあります。ループを使用して複数の行を処理します。プログラマーは、パラメーターを明示カーソルにも渡すことができます。

  • 例:明示カーソル

declare 
   cursor emp_cursor 
   is 
   select id,name,salary,dept_id 
   from employees; 
   v_id employees.id%type; 
   v_name employees.name%type; 
   v_salary employees.salary%type; 
   v_dept_id employees.dept_id%type; 
   begin 
   open emp_cursor; 
   loop 
   fetch emp_cursor into v_id,v_name,v_salary,v_dept_id; 
   exit when emp_cursor%notfound;
   dbms_output.put_line(v_id||', '||v_name||', '||v_salary||','||v_dept_id); 
   end loop;                    
   close emp_cursor; 
   end;
4
Ganesh Pathare

暗黙カーソルには、匿名バッファメモリが必要です。

明示カーソルは、その名前を使用して何度も実行できます。匿名カーソルメモリに保存されるのではなく、ユーザー定義のメモリ空間に保存されるため、後で簡単にアクセスできます。

3
prince
3
pablo

明示カーソルは、次のように宣言するカーソルです。

CURSOR my_cursor IS
  SELECT table_name FROM USER_TABLES

暗黙カーソルは、作成するインラインSQL(静的または動的)をサポートするために作成されます。

3
Dave Costa

最初の質問への回答。 Oracleから直接 ドキュメント

カーソルは、特定のSELECTまたはDMLステートメントの処理に関する情報を格納するプライベートSQL領域へのポインターです。

3
Ian Carpenter

明示カーソルを使用すると、データベース内の情報にアクセスする方法を完全に制御できます。カーソルを開くタイミング、カーソルから(したがってカーソルのSELECTステートメントのテーブルから)レコードをフェッチするタイミング、フェッチするレコード数、およびカーソルをクローズするタイミングを決定します。カーソルの現在の状態に関する情報は、カーソルの属性を調べることで入手できます。

詳細については、 http://www.unix.com.ua/orelly/Oracle/prog2/ch06_03.htm を参照してください。

2
Kristian

PL/SQLでは、カーソルはこのコンテキスト領域へのポインタです。ステートメントの処理に必要なすべての情報が含まれています。

暗黙カーソル:暗黙カーソルは、SQLステートメントが実行されるたびに、ステートメントに明示カーソルがない場合、Oracleによって自動的に作成されます。プログラマは、暗黙カーソルとその中の情報を制御できません。

明示カーソル:明示カーソルは、コンテキスト領域をより詳細に制御するためのプログラマー定義のカーソルです。 PL/SQLブロックの宣言セクションで明示カーソルを定義する必要があります。複数の行を返すSELECTステートメントで作成されます。

明示カーソルを作成するための構文は次のとおりです。

CURSOR cursor_name IS select_statement; 
1
GOVIND DIXIT

カーソルは、OracleテーブルのSELECTウィンドウです。これは、Oracleテーブルに存在し、特定の条件を満たすレコードのグループを意味します。カーソルは、テーブルのすべてのコンテンツも選択できます。カーソルを使用して、Oracle列を操作し、結果でエイリアスを作成できます。暗黙カーソルの例は次のとおりです。

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      FOR C1_REC IN C1
      LOOP
         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;
   END;
END;
/

FOR ... LOOP ... END LOOPを使用すると、カーソルのレコードがすべて分析されたときに、カーソルを自動的に開いたり閉じたりできます。

明示カーソルの例は次のとおりです。

BEGIN
   DECLARE
      CURSOR C1
      IS
         SELECT DROPPED_CALLS FROM ALARM_UMTS;

      C1_REC   C1%ROWTYPE;
   BEGIN
      OPEN c1;

      LOOP
         FETCH c1 INTO c1_rec;

         EXIT WHEN c1%NOTFOUND;

         DBMS_OUTPUT.PUT_LINE ('DROPPED CALLS: ' || C1_REC.DROPPED_CALLS);
      END LOOP;

      CLOSE c1;
   END;
END;
/

明示カーソルでは、明示的な方法でカーソルを開閉し、レコードの存在を確認し、終了条件を示します。

1
UltraCommit

Googleはあなたの友達です。 http://docstore.mik.ua/orelly/Oracle/prog2/ch06_03.htm

コードで明示カーソルを使用しない限り、PL/SQLでは、コードでSQL文を直接実行するたびに暗黙カーソルが発行されます。開発者であるSQLステートメントのカーソルを明示的に宣言しないため、「暗黙的な」カーソルと呼ばれます。

明示カーソルは、コードの宣言セクションで明示的に定義され、プロセスで名前が割り当てられたSELECTステートメントです。 UPDATE、DELETE、およびINSERTステートメントの明示的なカーソルのようなものはありません。

1
Derek Swingley

暗黙カーソルは1つのレコードのみを返し、自動的に呼び出されます。ただし、明示カーソルは手動で呼び出され、複数のレコードを返すことができます。

1
shaiksyedbasha

これは古い質問ですが、パフォーマンスの観点から2つの違いを示す実用的な例を追加するとよいと思います。

パフォーマンスの観点から、暗黙カーソルはより高速です。

2つのパフォーマンスの違いを見てみましょう。

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2    l_loops  NUMBER := 100000;
  3    l_dummy  dual.dummy%TYPE;
  4    l_start  NUMBER;
  5
  6    CURSOR c_dual IS
  7      SELECT dummy
  8      FROM   dual;
  9  BEGIN
 10    l_start := DBMS_UTILITY.get_time;
 11
 12    FOR i IN 1 .. l_loops LOOP
 13      OPEN  c_dual;
 14      FETCH c_dual
 15      INTO  l_dummy;
 16      CLOSE c_dual;
 17    END LOOP;
 18
 19    DBMS_OUTPUT.put_line('Explicit: ' ||
 20                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 21
 22    l_start := DBMS_UTILITY.get_time;
 23
 24    FOR i IN 1 .. l_loops LOOP
 25      SELECT dummy
 26      INTO   l_dummy
 27      FROM   dual;
 28    END LOOP;
 29
 30    DBMS_OUTPUT.put_line('Implicit: ' ||
 31                         (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 32  END;
 33  /
Explicit: 332 hsecs
Implicit: 176 hsecs

PL/SQL procedure successfully completed.

したがって、大きな違いがはっきりと見えます。

その他の例 こちら

1
Lalit Kumar B

Oracleデータベースによって実行されるすべてのSQLステートメントには、それに関連付けられたカーソルがあります。これは、処理情報を格納するためのプライベートな作業領域です。暗黙カーソルは、すべてのDMLおよびSELECTステートメントに対してOracleサーバーによって暗黙的に作成されます。

明示カーソルを宣言および使用して、プライベート作業領域に名前を付け、プログラムブロックに格納されている情報にアクセスできます。

0
ropable

他の回答で述べたように、暗黙カーソルは使いやすく、エラーが発生しにくいものです。

Oracle PL/SQLの暗黙カーソルと明示カーソル は、暗黙カーソルも明示カーソルよりも最大2倍高速であることを示しています。

誰もまだ言及していないのは奇妙です Impplicit FOR LOOP Cursor

begin
  for cur in (
    select t.id from parent_trx pt inner join trx t on pt.nested_id = t.id
    where t.started_at > sysdate - 31 and t.finished_at is null and t.extended_code is null
  )
  loop
    update trx set finished_at=sysdate, extended_code = -1 where id = cur.id;
    update parent_trx set result_code = -1 where nested_id = cur.id;
  end loop cur;
end;

SOの別の例: PL/SQL FOR LOOP IMPLICIT CURSOR

明示的な形式よりもずっと短いです。

これは、 CTEから複数のテーブルを更新する に対する素晴らしい回避策も提供します。

0
Vadzim