サーチ…


構文

  • カーソルcursor_nameyour_select_statementです。
  • Cursor cursor_name (param TYPE) your_select_statement_using_paramですか
  • FOR x in( your_select_statement )LOOP ...

備考

宣言されたカーソルは使用するのが難しく、ほとんどの場合FORループを優先するべきです。シンプルなFORループと比較して、カーソルで非常に興味深いのは、パラメータ化できるということです。

とにかくOracle SQLを使用するのではなく、PL / SQLおよびカーソルを使用してループを実行しない方がよいでしょう。しかし、手続き型言語に慣れている人にとっては、はるかに理解しやすくなります。

レコードが存在するかどうかを確認し、レコードが存在するかどうかに応じて異なるものを実行する場合は、カーソルループを使用するのではなく、純粋なORACLE SQLクエリでMERGEステートメント使用することが理にかなっています。 ( MERGEは、Oracleリリースでは9i以上でのみ使用可能です)。

パラメータ化された "FORループ"カーソル

DECLARE
  CURSOR c_emp_to_be_raised(p_sal emp.sal%TYPE) IS 
    SELECT * FROM emp WHERE  sal < p_sal;
BEGIN
  FOR cRowEmp IN c_emp_to_be_raised(1000) LOOP
    dbms_Output.Put_Line(cRowEmp .eName ||' ' ||cRowEmp.sal||'... should be raised ;)');
  END LOOP;
END;
/

暗黙の「FORループ」カーソル

BEGIN
  FOR x IN (SELECT * FROM emp WHERE sal < 100) LOOP
    dbms_Output.Put_Line(x.eName ||' '||x.sal||'... should REALLY be raised :D');
  END LOOP;
END;
/
  • 最初の利点は、退屈な宣言がないことです(あなたが以前のバージョンで持っていたこの恐ろしい "CURSOR"事を考えてください)
  • 2番目の利点は、最初に選択したクエリを作成してから、必要なものがあればすぐにPL / SQLループ内のクエリのフィールド( x.<myfield> )にアクセスできることです
  • ループはカーソルを開き、ループごとに一度に1レコードをフェッチします。ループの最後にカーソルが閉じられます。
  • 暗黙的なカーソルは、コードが長くなるにつれてインタープリタの仕事が増えるため、高速です。コードが少なくて済むので、通訳者の仕事が少なくて済みます。

SYS_REFCURSORの使用

SYS_REFCURSORは、表からではなく、より具体的には関数から返されたリストを簡単に処理する必要がある場合に、戻り値の型として使用できます。

カーソルを返す関数

CREATE OR REPLACE FUNCTION list_of (required_type_in IN VARCHAR2)
   RETURN SYS_REFCURSOR
IS
   v_ SYS_REFCURSOR;
BEGIN
   CASE required_type_in
      WHEN 'CATS'
      THEN
         OPEN v_ FOR
           SELECT nickname FROM (
                select 'minou' nickname from dual
      union all select 'minâ'           from dual
      union all select 'minon'          from dual         
           );
      WHEN 'DOGS'
      THEN
         OPEN v_ FOR
              SELECT dog_call FROM (
                select 'bill'   dog_call from dual
      union all select 'nestor'          from dual
      union all select 'raoul'           from dual         
           );
   END CASE;
   -- Whit this use, you must not close the cursor.
   RETURN v_;
END list_of;
/

とそれを使用する方法:

DECLARE
   v_names   SYS_REFCURSOR;
   v_        VARCHAR2 (32767);
BEGIN
   v_names := list_of('CATS');
   LOOP
      FETCH v_names INTO v_;
      EXIT WHEN v_names%NOTFOUND;
      DBMS_OUTPUT.put_line(v_);
   END LOOP;
   -- here you close it
   CLOSE v_names;
END;
/

カーソルの処理

  • カーソルを宣言してレコードのリストをスキャンする
  • それを開く
  • 現在のレコードを変数にフェッチする(これは位置をインクリメントする)
  • %notfoundを使用してリストの終わりを検出する
  • 現在のコンテキストでのリソース消費を制限するためにカーソルを閉じることを忘れないでください

-

DECLARE
  CURSOR curCols IS -- select column name and type from a given table
         SELECT column_name, data_type FROM all_tab_columns where table_name='MY_TABLE';
  v_tab_column all_tab_columns.column_name%TYPE;
  v_data_type all_tab_columns.data_type%TYPE;
  v_ INTEGER := 1;
BEGIN
  OPEN curCols;
  LOOP
     FETCH curCols INTO v_tab_column, v_data_type;
     IF curCols%notfound OR v_ > 2000 THEN
       EXIT;
     END IF;
     dbms_output.put_line(v_||':Column '||v_tab_column||' is of '|| v_data_type||' Type.');
     v_:= v_ + 1;
  END LOOP;

  -- Close in any case
  IF curCols%ISOPEN THEN  
     CLOSE curCols;
  END IF;
END;
/


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow