4.1 条件付き選択文

条件付き選択文IFおよびCASEは、データ値の違いに応じて異なる文を実行します。

IF文は、条件に応じて、一連の1つ以上の文を実行またはスキップします。IF文には次の形式があります。

  • IF THEN

  • IF THEN ELSE

  • IF THEN ELSIF

CASE文を使用すると、一連の条件を基に、対応する文を選択して実行できます。CASE文には次の形式があります。

  • 単純: 単一の式を評価して、可能性のある複数の値と比較します。

  • 検索: 複数の条件を評価して、最初にTRUEである条件を選択します。

CASE文は、オプションごとにアクションが異なる場合に適しています。

ここでのトピック

4.1.1 IF THEN文

IF THEN文は、条件に応じて、一連の1つ以上の文を実行またはスキップします。

IF THEN文の構造は、次のとおりです。

IF condition THEN
  statements
END IF;

conditionがTRUEの場合、statementsが実行されますが、それ以外の場合、IF文は何も実行しません。

構文の詳細は、「IF文」を参照してください。

ヒント:

次のようなIF文の使用は避けてください。

IF new_balance < minimum_balance THEN
  overdrawn := TRUE;
ELSE
  overdrawn := FALSE;
END IF;

かわりに、BOOLEAN式の値をBOOLEAN変数に直接代入してください。

overdrawn := new_balance < minimum_balance;

BOOLEAN変数は、TRUEFALSENULLのいずれかです。次のようには記述しないでください:

IF overdrawn = TRUE THEN
  RAISE insufficient_funds;
END IF;

かわりに、次のように記述してください:

IF overdrawn THEN
  RAISE insufficient_funds;
END IF;

例4-1 IF THEN文

この例では、salesの値がquota+200より大きい場合にのみ、THENEND IFの間にある文が実行されます。

DECLARE
  PROCEDURE p (
    sales  NUMBER,
    quota  NUMBER,
    emp_id NUMBER
  )
  IS
    bonus    NUMBER := 0;
    updated  VARCHAR2(3) := 'No';
  BEGIN
    IF sales > (quota + 200) THEN
      bonus := (sales - quota)/4;
 
      UPDATE employees
      SET salary = salary + bonus 
      WHERE employee_id = emp_id;
 
      updated := 'Yes';
    END IF;
 
    DBMS_OUTPUT.PUT_LINE (
      'Table updated?  ' || updated || ', ' || 
      'bonus = ' || bonus || '.'
    );
  END p;
BEGIN
  p(10100, 10000, 120);
  p(10500, 10000, 121);
END;
/
 

結果:

Table updated?  No, bonus = 0.
Table updated?  Yes, bonus = 125.

4.1.2 IF THEN ELSE文

IF THEN ELSE文の構造は、次のとおりです。

IF condition THEN
  statements
ELSE
  else_statements
END IF;

conditionの値がTRUEの場合、statementsが実行されますが、それ以外の場合は、else_statementsが実行されます。

例4-3に示すように、IF文はネストできます。

構文の詳細は、「IF文」を参照してください。

例4-2 IF THEN ELSE文

この例では、salesの値がquota+200より大きい場合にのみ、THENELSEの間にある文が実行されます。それ以外の場合は、ELSEEND IFの間にある文が実行されます。

DECLARE
  PROCEDURE p (
    sales  NUMBER,
    quota  NUMBER,
    emp_id NUMBER
  )
  IS
    bonus  NUMBER := 0;
  BEGIN
    IF sales > (quota + 200) THEN
      bonus := (sales - quota)/4;
    ELSE
      bonus := 50;
    END IF;
 
    DBMS_OUTPUT.PUT_LINE('bonus = ' || bonus);
 
    UPDATE employees
    SET salary = salary + bonus 
    WHERE employee_id = emp_id;
  END p;
BEGIN
  p(10100, 10000, 120);
  p(10500, 10000, 121);
END;
/

結果:

bonus = 50
bonus = 125

例4-3 ネストしたIF THEN ELSE文

DECLARE
  PROCEDURE p (
    sales  NUMBER,
    quota  NUMBER,
    emp_id NUMBER
  )
  IS
    bonus  NUMBER := 0;
  BEGIN
    IF sales > (quota + 200) THEN
      bonus := (sales - quota)/4;
    ELSE
      IF sales > quota THEN
        bonus := 50;
      ELSE
        bonus := 0;
      END IF;
    END IF;
 
    DBMS_OUTPUT.PUT_LINE('bonus = ' || bonus);
 
    UPDATE employees
    SET salary = salary + bonus 
    WHERE employee_id = emp_id;
  END p;
BEGIN
  p(10100, 10000, 120);
  p(10500, 10000, 121);
  p(9500, 10000, 122);
END;
/

結果:

bonus = 50
bonus = 125
bonus = 0

4.1.3 IF THEN ELSIF文

IF THEN ELSIF文の構造は、次のとおりです。

IF condition_1 THEN
  statements_1
ELSIF condition_2 THEN
  statements_2
[ ELSIF condition_3 THEN
    statements_3
]...
[ ELSE
    else_statements
]
END IF;

IF THEN ELSIF文は、conditionがTRUEである最初のstatementsを実行します。残りの条件は評価されません。TRUEのconditionがない場合は、else_statements(存在する場合)が実行されますが、else_statementsも存在しない場合、IF THEN ELSIF文は何も実行しません。

単一のIF THEN ELSIF文は、論理的に等価なネストしたIF THEN ELSE文より理解しやすい文です。

-- IF THEN ELSIF statement

IF condition_1 THEN statements_1;
  ELSIF condition_2 THEN statements_2;
  ELSIF condition_3 THEN statement_3;
END IF;

-- Logically equivalent nested IF THEN ELSE statements

IF condition_1 THEN
  statements_1;
ELSE
  IF condition_2 THEN
    statements_2;
  ELSE
    IF condition_3 THEN
      statements_3;
    END IF;
  END IF;
END IF;

構文の詳細は、「IF文」を参照してください。

例4-4 IF THEN ELSIF文

この例では、salesの値が50000より大きい場合、1番目と2番目の条件のいずれもTRUEになります。ただし、1番目の条件がTRUEであるため、bonusには1500という値が代入され、2番目の条件はテストされません。bonusに値1500が代入された後、制御はDBMS_OUTPUT.PUT_LINEの起動に移ります。

DECLARE
  PROCEDURE p (sales NUMBER)
  IS
    bonus  NUMBER := 0;
  BEGIN 
    IF sales > 50000 THEN
      bonus := 1500;
    ELSIF sales > 35000 THEN
      bonus := 500;
    ELSE
      bonus := 100;
    END IF;
 
    DBMS_OUTPUT.PUT_LINE (
      'Sales = ' || sales || ', bonus = ' || bonus || '.'
    );
  END p;
BEGIN
  p(55000);
  p(40000);
  p(30000);
END;
/

結果:

Sales = 55000, bonus = 1500.
Sales = 40000, bonus = 500.
Sales = 30000, bonus = 100.

例4-5 単純なCASE文をシミュレートするIF THEN ELSIF文

この例では、IF THEN ELSIF文を多数のELSIF句とともに使用し、単一の値を多くの使用可能な値と比較しています。この目的では、単純なCASE文の方がより明確になります(例4-6を参照)。

DECLARE
  grade CHAR(1);
BEGIN
  grade := 'B';
  
  IF grade = 'A' THEN
    DBMS_OUTPUT.PUT_LINE('Excellent');
  ELSIF grade = 'B' THEN
    DBMS_OUTPUT.PUT_LINE('Very Good');
  ELSIF grade = 'C' THEN
    DBMS_OUTPUT.PUT_LINE('Good');
  ELSIF grade = 'D' THEN
    DBMS_OUTPUT. PUT_LINE('Fair');
  ELSIF grade = 'F' THEN
    DBMS_OUTPUT.PUT_LINE('Poor');
  ELSE
    DBMS_OUTPUT.PUT_LINE('No such grade');
  END IF;
END;
/
 

結果:

Very Good

4.1.4 単純なCASE文

単純なCASE文の構造は、次のとおりです。

CASE selector
WHEN selector_value_1 THEN statements_1
WHEN selector_value_2 THEN statements_2
...
WHEN selector_value_n THEN statements_n
[ ELSE
  else_statements ]
END CASE;]

selectorは式です(通常は1つの変数)。各selector_valueはリテラルまたは式のいずれかです。(構文の詳細は、「CASE文」を参照してください。)

単純なCASE文は、selector_valueselectorと等しい最初のstatementsを実行します。残りの条件は評価されません。いずれのselector_valueselectorと等しくない場合、CASE文はelse_statements(存在する場合)を実行しますが、else_statementsが存在しない場合は、事前定義の例外CASE_NOT_FOUNDを呼び出します。

例4-6では、単純なCASE文を使用して、単一の値を多くの使用可能な値と比較しています。例4-6CASE文は、例4-5IF THEN ELSIF文と論理的に等価です。

ノート:

単純なCASE式と同様に、単純なCASE文の選択子の値がNULLの場合、その選択子がWHEN NULLによって一致することはありません(例2-51を参照)。かわりに、検索CASE文をWHEN condition IS NULLとともに使用します(例2-53 を参照)。

例4-6 単純なCASE文

DECLARE
  grade CHAR(1);
BEGIN
  grade := 'B';

  CASE grade
    WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
    WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
    WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
    WHEN 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
    WHEN 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
    ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
  END CASE;
END;
/
 

結果:

Very Good

4.1.5 検索CASE文

検索CASE文の構造は、次のとおりです。

CASE
WHEN condition_1 THEN statements_1
WHEN condition_2 THEN statements_2
...
WHEN condition_n THEN statements_n
[ ELSE
  else_statements ]
END CASE;]

検索CASE文は、conditionがTRUEである最初のstatementsを実行します。残りの条件は評価されません。TRUEのconditionがない場合、CASE文はelse_statements(存在する場合)を実行しますが、else_statementsも存在しない場合は、事前定義の例外CASE_NOT_FOUNDを呼び出します。(構文の詳細は、「CASE文」を参照してください。)

例4-7の検索CASE文は、例4-6の単純なCASE文と論理的に等価です。

例4-7例4-6のいずれの場合も、ELSE句をEXCEPTION部に置き換えることができます。例4-8は、例4-7と論理的に等価です。

例4-7 検索CASE文

DECLARE
  grade CHAR(1);
BEGIN
  grade := 'B';
  
  CASE
    WHEN grade = 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
    WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
    WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
    WHEN grade = 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
    WHEN grade = 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
    ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
  END CASE;
END;
/
 

結果:

Very Good

例4-8 CASE文でのELSE句にかわるEXCEPTION

DECLARE
  grade CHAR(1);
BEGIN
  grade := 'B';
  
  CASE
    WHEN grade = 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
    WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
    WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
    WHEN grade = 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
    WHEN grade = 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
  END CASE;
EXCEPTION
  WHEN CASE_NOT_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('No such grade');
END;
/
 

結果:

Very Good