例外処理後に実行を続ける方法

例外ハンドラが実行されると、外側のブロック(外側のブロックがない場合は起動元またはホスト環境)の次の文に制御が移ります。例外ハンドラは、そのハンドラが存在するブロックに制御を取り戻すことができません。

たとえば、例12-24では、SELECT INTO文でZERO_DIVIDEが呼び出され、例外ハンドラがこれを処理した後に、SELECT INTO文に続くINSERT文から続けて実行することができません。

SELECT INTO文に続くINSERT文から実行を再開する必要がある場合は、例12-25に示すとおり、独自のZERO_DIVIDE例外ハンドラを持つ内側のブロックにSELECT INTO文を配置します。

関連項目:

例13-13では、例外が発生してもバルクSQL操作が継続されます

例12-24 例外ハンドラの実行と実行の終了

DROP TABLE employees_temp;
CREATE TABLE employees_temp AS
  SELECT employee_id, salary, commission_pct
  FROM employees;
 
DECLARE
  sal_calc NUMBER(8,2);
BEGIN
  INSERT INTO employees_temp (employee_id, salary, commission_pct)
  VALUES (301, 2500, 0);
 
  SELECT (salary / commission_pct) INTO sal_calc
  FROM employees_temp
  WHERE employee_id = 301;
 
  INSERT INTO employees_temp VALUES (302, sal_calc/100, .1);
  DBMS_OUTPUT.PUT_LINE('Row inserted.');
EXCEPTION
  WHEN ZERO_DIVIDE THEN
    DBMS_OUTPUT.PUT_LINE('Division by zero.');
END;
/

結果:

Division by zero.

例12-25 例外ハンドラの実行と実行の継続

DECLARE
  sal_calc NUMBER(8,2);
BEGIN
  INSERT INTO employees_temp (employee_id, salary, commission_pct)
  VALUES (301, 2500, 0);
 
  BEGIN
    SELECT (salary / commission_pct) INTO sal_calc
    FROM employees_temp
    WHERE employee_id = 301;
  EXCEPTION
    WHEN ZERO_DIVIDE THEN
      DBMS_OUTPUT.PUT_LINE('Substituting 2500 for undefined number.');
      sal_calc := 2500;
  END;
 
  INSERT INTO employees_temp VALUES (302, sal_calc/100, .1);
  DBMS_OUTPUT.PUT_LINE('Enclosing block: Row inserted.');
EXCEPTION
  WHEN ZERO_DIVIDE THEN
    DBMS_OUTPUT.PUT_LINE('Enclosing block: Division by zero.');
END;
/

結果:

Substituting 2500 for undefined number.
Enclosing block: Row inserted.