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

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

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

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

レコードについて

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

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

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

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

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

TYPE record_name IS RECORD
  ( field_name data_type [:= initial_value]
 [, field_name data_type [:= initial_value ] ]... );

variable_name record_name;

関連情報:

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

このチュートリアルでは、SQL Developerの編集ツールを使用してRECORD型のsal_infoを宣言する方法を示します。フィールドには、従業員ジョブID、そのジョブIDの給与の最小値および最大値、現在の給与、推奨される昇給などの、従業員の給与情報を格納できます。

レコード型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」ペインで、太字フォントで示されているコードを次の位置に入力します。

    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. 「コンパイル」をクリックします。

カーソルについて

データベースが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)。表5-1に、カーソル属性および戻すことのできる値のリストを示します。(暗黙カーソルにはさらに属性がありますが、このマニュアルの範囲を超えています。)

表1カーソル属性の値

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

カーソルは開くがフェッチが試行されない場合は、NULLです。

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

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

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

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

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

%NOTFOUND

カーソルは開くがフェッチが試行されない場合は、NULLです。

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

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

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

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

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

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

カーソルが開いていない場合、%FOUND、%NOTFOUNDおよび%ROWCOUNT属性は事前定義済の例外INVALID_CURSORを発生します。

関連情報:

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

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

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

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

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

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

      CURSOR cursor_name IS query;

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

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

      record_name cursor_name%ROWTYPE;

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

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

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

      OPEN cursor_name;

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

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

      CLOSE cursor_name;

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

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

      cursor_variable cursor_type;

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

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

      record_name return_type;

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

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

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

      OPEN cursor_variable FOR query;

      OPEN FOR文の構文の詳細は、Oracle AI 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 AI Database PL/SQL言語リファレンスに関する項を参照してください。

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

      CLOSE cursor_variable;

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

      CLOSE文の構文の詳細は、Oracle AI 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. 次に太字フォントで示されているように、部門ごとに3つの結果セットを取得し、EVAL_LOOP_CONTROLプロシージャを起動するよう、EVAL_DEPARTMENTプロシージャを変更します。

    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パッケージ本体をコンパイルします。