レコードおよびカーソルの使用

このページのスクリプト・コンテンツはナビゲーションのみを目的としており、いかなる方法においても内容を変更するものではありません。

レコードにデータ値を格納し、カーソルを結果セットおよび関連の処理情報へのポインタとして使用できます。

関連項目:レコードの詳細は『Oracle Database PL/SQL言語リファレンス』を参照してください。

レコードについて

レコードは、様々な型のデータ値を格納できるPL/SQLコンポジット変数です。内部コンポーネント(フィールド)はスカラー変数と同様に処理できます。サブプログラム・パラメータとしてレコード全体を渡すことができます。レコードは、表の行または表の行の特定の列からデータを保持する場合に有用です。

レコードは、様々な型のデータ値を格納できるPL/SQLコンポジット変数で、C、C++またはJavaの0型に似ています。レコードの内部コンポーネントは、フィールドと呼ばれます。レコード・フィールドにアクセスするには、ドット表記法(record_name.field_name)を使用します。

レコード・フィールドはスカラー変数のように処理できます。サブプログラム・パラメータとしてレコード全体を渡すこともできます。

レコードは、表の行または表の行の特定の列からデータを保持する場合に有用です。各レコード・フィールドは表の列に対応しています。

レコードを作成するには、3つの方法があります。

関連情報:

チュートリアル: レコード型の宣言

次のステップは、SQL Developerの編集ツールを使用してRECORD型sal_infoを宣言する方法を示しています。この型には、各従業員の給与情報(ジョブID、最小および最大給与、現在の給与、推奨される昇給額など)を保持するためのフィールドがあります。

RECORD型のsal_infoを宣言するステップ:

  1. 「接続」フレームのhr_connを開きます。

    hr_connアイコンの下に、スキーマ・オブジェクト・タイプのリストが表示されます。

  2. 「パッケージ」を開きます。

    パッケージのリストが表示されます。

  3. EMP_EVALを右クリックします。

    選択リストが表示されます。

  4. 「編集」を選択します。

    EMP_EVALペインが開き、パッケージを作成したCREATE PACKAGE文が表示されます:

    CREATE OR REPLACE PACKAGE EMP_EVAL AS
       
    PROCEDURE eval_department(dept_id IN NUMBER);
    FUNCTION calculate_score(evaluation_id IN NUMBER
                           , performance_id IN NUMBER)
                             RETURN NUMBER;
       
    END EMP_EVAL;
    
  5. EMP_EVALペインで、END EMP_EVALの直前に次のコードを追加します。

     TYPE sal_info IS RECORD
       ( j_id     jobs.job_id%type
       , sal_min  jobs.min_salary%type
       , sal_max  jobs.max_salary%type
       , sal      employees.salary%type
       , sal_raise NUMBER(3,3) );
    

    ペインのタイトルがイタリック・フォントで表示されますが、これは、データベースに変更が保存されていないことを示します。

  6. 「コンパイル」アイコンを選択します。

    変更したパッケージ仕様部がコンパイルされ、データベースに保存されます。EMP_EVALペインのタイトルは、もはやイタリック・フォントでなくなります。

    これで、「チュートリアル: レコード・パラメータを使用したサブプログラムの作成と起動」で説明されているように、型がsal_infoのレコードを宣言できます。

チュートリアル: レコード・パラメータを使用したサブプログラムの作成と起動

次のステップでは、SQL Developerの編集ツールを使用してレコード型sal_infoのパラメータでサブプログラムを作成および起動します。

レコード型sal_infoは、「チュートリアル: RECORD型の宣言」で作成しました。

このチュートリアルでは、SQL Developerの編集ツールを使用して次のタスクを実行する方法を示します。

EVAL_FREQUENCYはSALARY_SCHEDULEを起動するため、SALARY_SCHEDULEの宣言は、EVAL_FREQUENCYの宣言の前に行わなければなりません(そうでないと、パッケージはコンパイルしません)。ただし、SALARY_SCHEDULEの定義は、パッケージ本体のどこで実行しても構いません。

SALARY_SCHEDULEを作成し、EVAL_FREQUENCYを変更するステップ:

  1. 「接続」フレーム内で、hr_connを展開します

  2. スキーマ・オブジェクト・タイプのリスト内で、「パッケージ」を展開します。

  3. パッケージのリストで、EMP_EVALを展開します。

  4. 選択肢のリストで、EMP_EVALの本体を右クリックします。

  5. 選択肢のリストで、「編集」を選択します。

    EMP_EVAL本体ペインが表示され、パッケージ本体のコードが示されます。

  6. EMP_EVAL本体ペインで、END EMP_EVALの直前にSALARY_SCHEDULEプロシージャの以下の定義を追加します。

     PROCEDURE salary_schedule (emp IN sal_info) AS
       accumulating_sal  NUMBER;
     BEGIN
       DBMS_OUTPUT.PUT_LINE('If salary ' || emp.sal ||
         ' increases by ' || ROUND((emp.sal_raise * 100),0) ||
    
         '% each year, it will be:');
    
       accumulating_sal := emp.sal;
    
       WHILE accumulating_sal <= emp.sal_max LOOP
         accumulating_sal := accumulating_sal * (1 + emp.sal_raise);
         DBMS_OUTPUT.PUT_LINE(ROUND(accumulating_sal,2) ||', ');
    
       END LOOP;
     END salary_schedule;
    

    ペインのタイトルがイタリック・フォントで表示されますが、これは、データベースに変更が保存されていないことを示します。

  7. 「EMP_EVAL Body」ペインで、eval_frequencyファンクションとsalary_scheduleプロシージャおよびadd_evalプロシージャを次の位置に入力します。

     CREATE OR REPLACE
     PACKAGE BODY EMP_EVAL AS
    
     FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE)
    
       RETURN PLS_INTEGER;
    
     PROCEDURE salary_schedule(emp IN sal_info);
    
     PROCEDURE add_eval(employee_id IN employees.employee_id%type, today IN DATE);
    
     PROCEDURE eval_department (dept_id IN NUMBER) AS
    
  8. EVAL_FREQUENCYファンクションを編集し、次の変更を行います。

     FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE)
       RETURN PLS_INTEGER
     AS
       h_date     EMPLOYEES.HIRE_DATE%TYPE;
       today      EMPLOYEES.HIRE_DATE%TYPE;
       eval_freq  PLS_INTEGER;
    
       emp_sal    SAL_INFO;  -- replaces sal, sal_raise, and sal_max
    
     BEGIN
       SELECT SYSDATE INTO today FROM DUAL;
    
       SELECT HIRE_DATE INTO h_date
       FROM EMPLOYEES
       WHERE EMPLOYEE_ID = eval_frequency.emp_id;
    
       IF ((h_date + (INTERVAL '120' MONTH)) < today) THEN
         eval_freq := 1;
    
         /* populate emp_sal */
    
         SELECT j.JOB_ID, j.MIN_SALARY, j.MAX_SALARY, e.SALARY
    
         INTO emp_sal.j_id, emp_sal.sal_min, emp_sal.sal_max, emp_sal.sal
    
         FROM EMPLOYEES e, JOBS j
    
         WHERE e.EMPLOYEE_ID = eval_frequency.emp_id
    
         AND j.JOB_ID = eval_frequency.emp_id;
    
         emp_sal.sal_raise := 0;  -- default
    
         CASE emp_sal.j_id
           WHEN 'PU_CLERK' THEN emp_sal.sal_raise := 0.08;
           WHEN 'SH_CLERK' THEN emp_sal.sal_raise := 0.07;
           WHEN 'ST_CLERK' THEN emp_sal.sal_raise := 0.06;
           WHEN 'HR_REP' THEN emp_sal.sal_raise := 0.05;
           WHEN 'PR_REP' THEN emp_sal.sal_raise := 0.05;
           WHEN 'MK_REP' THEN emp_sal.sal_raise := 0.04;
           ELSE NULL;
         END CASE;
    
         IF (emp_sal.sal_raise != 0) THEN
    
           salary_schedule(emp_sal);
         END IF;
       ELSE
         eval_freq := 2;
       END IF;
    
       RETURN eval_freq;
     END eval_frequency;
    
  9. 「コンパイル」を選択します。

カーソルについて

Oracle DatabaseによりSQL文が実行される場合、結果セットおよび処理情報は、名前が指定されていないプライベートSQL領域に格納されます。この名前のない領域へのポインタは、カーソルと呼ばれ、これを使って結果セットを1行ずつ取得することができます。カーソルの属性は、カーソルの状態に関する情報を返します。

SQL DML文またはPL/SQL SELECT INTO文を実行するたびに、PL/SQLによって暗黙カーソルがオープンされます。このカーソルに関する情報はその属性から取得できますが、制御することはできません。文を実行後にカーソルは閉じますが、その属性値は、別のDMLまたはSELECT INTO文が実行するまで使用可能なままです。

PL/SQLを使用すれば、カーソルも宣言できます。宣言カーソルには名前があり、問合せ(SQL SELECT文)に関連付けられています。通常、複数行が返されます。カーソルを宣言した後、暗黙的または明示的に処理する必要があります。カーソルを暗黙的に処理するには、カーソルFOR LOOPを使用します。構文:

FOR record_name IN cursor_name LOOP
  statement
  [ statement ]...
END LOOP;

カーソルを明示的に処理するには、カーソルを開き(OPEN文)、結果セットから1つずつまたは一括して行をフェッチし(FETCH文を使用)、カーソルを閉じます(CLOSE文を使用)。カーソルを閉じると、結果セットからレコードをフェッチすることも、カーソルの属性値を表示することもできません。

暗黙カーソル属性の値の構文は、SQL%attribute (SQL%FOUNDなど)です。SQL%attributeは、常に最後に実行されたDMLまたはSELECT INTO文を参照します。

宣言されたカーソル属性値の構文は、cursor_name%attributeです(たとえば、c1%FOUND)。表1に、カーソル属性および戻すことのできる値のリストを示します。(暗黙カーソルにはさらに属性がありますが、このマニュアルの範囲を超えています。)

表1カーソル属性の値

属性 宣言カーソルの値 暗黙カーソルの値
%FOUND

カーソルはオープンされているが、フェッチが試みられていない場合、NULL

最近のフェッチで行が返された場合は、TRUEです。

最近のフェッチで行が返されなかった場合は、FALSEです。

DMLまたは SELECT INTO文が実行していない場合は、NULLです。

最新のDMLまたはSELECT INTO文で行が返された場合は、TRUEです。

最新のDMLまたはSELECT INTO文で行が返されなかった場合は、FALSEです。

%NOTFOUND

カーソルはオープンされているが(脚注1)、フェッチが試行されなかった場合は、NULLです。

最近のフェッチで行が返された場合は、FALSEです。

最近のフェッチで行が返されなかった場合は、TRUEです。

DMLまたは SELECT INTO文が実行していない場合は、NULLです。

最新のDMLまたはSELECT INTO文で行が返された場合は、FALSEです。

最新のDMLまたはSELECT INTO文で行が返されなかった場合は、TRUEです。

%ROWCOUNT カーソルが開いている場合(脚注1)、0以上の数字です。 DML文またはSELECT INTO文が実行されなかった場合は、NULLです。そうでない場合は、0以上の数字です。
%ISOPEN カーソルが開いている場合はTRUE、開いていない場合はFALSEです。 常にFALSE。

脚注1:カーソルが開いていない場合、属性は事前定義済の例外INVALID_CURSORを発生します。

関連情報:

宣言カーソルを使用して結果セットの行を1行ずつ取得

宣言カーソルを使用して結果セットの行を1行ずつ取得できます。

次の手順では、最も単純な形式で必要な各文を使用し、複雑な構文への参照も提示します。

宣言カーソルを使用して、結果セットの行を1行ずつ取得するステップ:

  1. 宣言部で次を実行します。

    1. カーソルを宣言します。

       CURSOR cursor_name IS query;
      

      宣言カーソルの宣言構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    2. レコードを宣言して、カーソルで返される行を保持します。

       record_name cursor_name%ROWTYPE;
      

      %ROWTYPE構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

  2. 実行可能部で次を実行します。

    1. カーソルを開きます。

       OPEN cursor_name;
      

      OPEN文の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    2. 次に、似た構文を持つLOOP文を使用して、カーソルから行(結果セットからの行数)を1つずつフェッチします。

       LOOP
         FETCH cursor_name INTO record_name;
         EXIT WHEN cursor_name%NOTFOUND;
      
         -- Process row that is in record_name:
      
         statement;
         [ statement; ]...
       END LOOP;
      

      FETCH文の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    3. カーソルを閉じます。

       CLOSE cursor_name;
      

CLOSE文の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

チュートリアル: 宣言カーソルを使用して結果セットの行を1行ずつ取得

次のステップでは、宣言カーソルemp_cursorを使用するプロシージャEMP_EVAL.EVAL_DEPARTMENTの実装方法を示しています。

EMP_EVAL.EVAL_DEPARTMENTプロシージャを実装するステップ:

  1. EMP_EVALパッケージ仕様部で、EVAL_DEPARTMENTプロシージャを次のように宣言します。

     PROCEDURE eval_department(dept_id IN employees.department_id%TYPE);
    
  2. EMP_EVALパッケージ本体で、次の例で示されているように、EVAL_DEPARTMENTプロシージャの定義を変更します。

     PROCEDURE eval_department (dept_id IN employees.department_id%TYPE)
     AS
    
       CURSOR emp_cursor IS
    
         SELECT * FROM EMPLOYEES
    
         WHERE DEPARTMENT_ID = eval_department.dept_id;
    
       emp_record  EMPLOYEES%ROWTYPE;  -- for row returned by cursor
    
       all_evals   BOOLEAN;  -- true if all employees in dept need evaluations
    
       today       DATE;
    
     BEGIN
    
       today := SYSDATE;
    
       IF (EXTRACT(MONTH FROM today) < 6) THEN
    
         all_evals := FALSE; -- only new employees need evaluations
    
       ELSE
    
         all_evals := TRUE;  -- all employees need evaluations
    
       END IF;
    
       OPEN emp_cursor;
    
       DBMS_OUTPUT.PUT_LINE (
    
         'Determining evaluations necessary in department # ' ||
    
         dept_id );
    
       LOOP
    
         FETCH emp_cursor INTO emp_record;
    
         EXIT WHEN emp_cursor%NOTFOUND;
    
         IF all_evals THEN
    
           add_eval(emp_record.employee_id, today);
    
         ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN
    
           add_eval(emp_record.employee_id, today);
    
         END IF;
    
       END LOOP;
    
       DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.');
    
       CLOSE emp_cursor;
     END eval_department;
    

    (パッケージ本体の変更のステップ例は、「チュートリアル: サブプログラム内の変数および定数の宣言」を参照してください)。

  3. EMP_EVALパッケージ仕様部をコンパイルします。

  4. EMP_EVALパッケージ本体をコンパイルします。

カーソル変数について

カーソル変数は、1つの問合せに限定されないカーソルのようなものです。問合せのカーソル変数を開いて、結果セットを処理し、別の問合せのカーソル変数を使用することができます。カーソル変数は、サブプログラム間で問合せ結果を渡すときに有用です。

カーソルの詳細は、「カーソルについて」を参照してください。

カーソル変数の宣言には、REF CURSOR型を宣言してから、その型の変数(このため、カーソル変数はREF CURSORと呼ばれることもあります)を宣言します。REF CURSOR型には強弱があります。

強いREF CURSOR型の場合は、戻り型にこのカーソル変数のRECORD型が指定されます。PL/SQLコンパイラでは、これらの強い型のカーソル変数を問合せに使用して、戻り型ではない行を返すことはできません。強いREF CURSOR型は、弱い型よりミスが発生する可能性は低いですが、弱い型のほうがより柔軟です。

弱いREF CURSOR型では、戻り型は指定されません。PL/SQLコンパイラでは、弱い型のカーソル変数を問合せに使用することができます。弱いREF CURSOR型は互換性があり、このため、弱いREF CURSOR型を作成するかわりに、事前定義の弱いカーソル型SYS_REFCURSORを使用できます。

カーソル変数を宣言したら、特定の問合せでその変数を開き(OPEN FOR文を使用)、結果セットから1行ずつ行をフェッチし(FETCH文を使用)、カーソルを閉じるか(CLOSE文を使用)、別の問合せに対してカーソルを開きます(OPEN FOR文を使用)。別の問合せに対してカーソル変数を開くと、前の問合せのカーソル変数は閉じます。特定の問合せのカーソル変数を閉じた後は、問合せの結果セットからレコードをフェッチすることも、その問合せのカーソル属性値を参照することもできません。

関連情報:

カーソル変数を使用して結果セットの行を1行ずつ取得

カーソル変数を使用して結果セットの行を1行ずつ取得できます。

次の手順では、最も単純な形式で必要な各文を使用し、複雑な構文への参照も提示します。

カーソル変数を使用して結果セットの行を1行ずつ取得するステップ:

  1. 宣言部で次を実行します。

    1. REF CURSOR型を宣言します。

       TYPE cursor_type IS REF CURSOR [ RETURN return_type ];
      

      REF CURSOR型の宣言構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    2. この型のカーソル変数を宣言するには、次の手順を実行します。

       cursor_variable cursor_type;
      

      カーソル変数値の宣言構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    3. レコードを宣言して、カーソルで返される行を保持します。

       record_name return_type;
      

      レコード宣言の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

  2. 実行可能部で次を実行します。

    1. 特定の問合せのカーソル変数を開きます。

       OPEN cursor_variable FOR query;
      

      OPEN FOR文の構文の詳細は、『Oracle Database PL/SQL言語リファレンス』に関する項を参照してください。

    2. 次のような構文のLOOP文を使用して、カーソル変数(結果セットからの行)から1つずつ行をフェッチします。

       LOOP
         FETCH cursor_variable INTO record_name;
         EXIT WHEN cursor_variable%NOTFOUND;
      
         -- Process row that is in record_name:
      
         statement;
         [ statement; ]...
       END LOOP;
      

      FETCH文の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    3. カーソル変数を閉じます。

       CLOSE cursor_variable;
      

      または、別の問合せのカーソル変数を開きます。これにより、現在の問合せに対するカーソル変数は閉じます。

      CLOSE文の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

チュートリアル: カーソル変数を使用して結果セットの行を1行ずつ取得

この後のステップでは、EMP_EVAL.EVAL_DEPARTMENTプロシージャを変更して、宣言カーソル(複数の部門を処理できる)のかわりにカーソル変数を使用する方法と、EMP_EVAL.EVAL_DEPARTMENTおよびEMP_EVAL.ADD_EVALのより効率的な使用方法について説明します。

このチュートリアルでは、EMP_EVAL.EVAL_DEPARTMENTおよびEMP_EVAL.ADD_EVALのより効率的な使用方法を示します。レコードの1つのフィールドをADD_EVALに渡して、ADD_EVALで同じレコード内の他の3つのフィールドを抽出する3つの問合せを使用するかわりに、EVAL_DEPARTMENTはレコード全体をADD_EVALに渡し、ADD_EVALは、ドット表記法を使用して他の3つのフィールドの値にアクセスします。

EMP_EVAL.EVAL_DEPARTMENTプロシージャを変更して、カーソル変数を使用するには:

  1. EMP_EVALパッケージ仕様部で、次の例に示すように、プロシージャの宣言およびREF CURSOR型の定義を追加します。

     CREATE OR REPLACE
     PACKAGE emp_eval AS
    
       PROCEDURE eval_department (dept_id IN employees.department_id%TYPE);
    
       PROCEDURE eval_everyone;
    
       FUNCTION calculate_score(eval_id IN scores.evaluation_id%TYPE
                             , perf_id IN scores.performance_id%TYPE)
                               RETURN NUMBER;
       TYPE SAL_INFO IS RECORD
           ( j_id jobs.job_id%type
           , sal_min jobs.min_salary%type
           , sal_max jobs.max_salary%type
           , salary employees.salary%type
           , sal_raise NUMBER(3,3));
    
       TYPE emp_refcursor_type IS REF CURSOR RETURN employees%ROWTYPE;
     END emp_eval;
    
  2. EMP_EVALパッケージ本体で、次に太字で示されているように、プロシージャEVAL_LOOP_CONTROLのフォワード宣言を追加し、プロシージャADD_EVALの宣言を変更します。

     CREATE OR REPLACE
     PACKAGE BODY EMP_EVAL AS
    
       FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
         RETURN PLS_INTEGER;
    
       PROCEDURE salary_schedule(emp IN sal_info);
    
       PROCEDURE add_eval(emp_record IN EMPLOYEES%ROWTYPE, today IN DATE);
    
       PROCEDURE eval_loop_control(emp_cursor IN emp_refcursor_type);
     ...
    

    (パッケージ本体の変更のステップ例は、「チュートリアル: サブプログラム内の変数および定数の宣言」を参照してください)。

  3. EVAL_DEPARTMENTプロシージャを変更して、部門に基づいた3つの異なる結果セットを取得し、EVAL_LOOP_CONTROLプロシージャを起動するように、次の例に示すように変更します。

     PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
    
       emp_cursor    emp_refcursor_type;
    
       current_dept  departments.department_id%TYPE;
    
     BEGIN
    
       current_dept := dept_id;
    
       FOR loop_c IN 1..3 LOOP
    
         OPEN emp_cursor FOR
    
           SELECT *
    
           FROM employees
    
           WHERE current_dept = eval_department.dept_id;
    
         DBMS_OUTPUT.PUT_LINE
           ('Determining necessary evaluations in department #' ||
    
           current_dept);
    
         eval_loop_control(emp_cursor);
    
         DBMS_OUTPUT.PUT_LINE
           ('Processed ' || emp_cursor%ROWCOUNT || ' records.');
    
         CLOSE emp_cursor;
    
         current_dept := current_dept + 10;
    
       END LOOP;
     END eval_department;
    
  4. ADD_EVALプロシージャを次のように変更します。

     PROCEDURE add_eval(emp_record IN employees%ROWTYPE, today IN DATE)
     AS
    
     -- (Delete local variables)
     BEGIN
       INSERT INTO EVALUATIONS (
         evaluation_id,
         employee_id,
         evaluation_date,
         job_id,
         manager_id,
         department_id,
         total_score
       )
       VALUES (
         evaluations_sequence.NEXTVAL,   -- evaluation_id
    
         emp_record.employee_id,    -- employee_id
         today,                     -- evaluation_date
    
         emp_record.job_id,         -- job_id
    
         emp_record.manager_id,     -- manager_id
    
         emp_record.department_id,  -- department_id
         0                           -- total_score
     );
     END add_eval;
    
  5. END EMP_EVALの前に、次のプロシージャを追加して、個々のレコードを結果セットからフェッチして処理します。

     PROCEDURE eval_loop_control (emp_cursor IN emp_refcursor_type) AS
       emp_record      EMPLOYEES%ROWTYPE;
       all_evals       BOOLEAN;
       today           DATE;
     BEGIN
       today := SYSDATE;
    
       IF (EXTRACT(MONTH FROM today) < 6) THEN
    
         all_evals := FALSE;
       ELSE
         all_evals := TRUE;
       END IF;
    
       LOOP
         FETCH emp_cursor INTO emp_record;
         EXIT WHEN emp_cursor%NOTFOUND;
    
         IF all_evals THEN
           add_eval(emp_record, today);
         ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN
    
           add_eval(emp_record, today);
         END IF;
       END LOOP;
     END eval_loop_control;
    
  6. END EMP_EVALの前に、次のプロシージャを追加して、社内の全従業員を含む結果セットを取得します。

     PROCEDURE eval_everyone AS
       emp_cursor emp_refcursor_type;
     BEGIN
       OPEN emp_cursor FOR SELECT * FROM employees;
       DBMS_OUTPUT.PUT_LINE('Determining number of necessary evaluations.');
       eval_loop_control(emp_cursor);
       DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.');
       CLOSE emp_cursor;
     END eval_everyone;
    
  7. EMP_EVALパッケージ仕様部をコンパイルします。

  8. EMP_EVALパッケージ本体をコンパイルします。