条件付き選択文
条件付き選択文のIF
およびCASE
は、データ値の違いに応じて異なる文を実行します。
IF
文は、条件に応じて、一連の1つ以上の文を実行またはスキップします。IF
文には次の形式があります。
-
IF
THEN
-
IF
THEN
ELSE
-
IF
THEN
ELSIF
CASE
文を使用すると、一連の条件を基に、対応する文を選択して実行できます。CASE
文には次の形式があります。
-
単純な
CASE
文は、単一の式を評価して、複数の可能性のある値と比較します。 -
検索
CASE
文は、複数の条件を評価して、最初にTRUEになる条件を選択します。
CASE
文は、オプションごとにアクションが異なる場合に適しています。
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
変数は、TRUE
、FALSE
、NULL
のいずれかです。次のようには記述しないでください:
IF overdrawn = TRUE THEN RAISE insufficient_funds; END IF;
かわりに、次のように記述してください:
IF overdrawn THEN RAISE insufficient_funds; END IF;
例5-1 IF THEN文
この例では、sales
の値がquota
+200より大きい場合にのみ、THEN
とEND
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.
IF THEN ELSE文
IF
THEN
ELSE
文の構造は、次のとおりです。
IF condition THEN statements ELSE else_statements END IF;
condition
の値がTRUEの場合、statements
が実行されますが、それ以外の場合は、else_statements
が実行されます。
例5-3に示すように、IF
文はネストできます。
構文の詳細は、「IF文」を参照してください。
例5-2 IF THEN ELSE文
この例では、sales
の値がquota
+200より大きい場合にのみ、THEN
とELSE
の間にある文が実行されます。それ以外の場合は、ELSE
とEND
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
例5-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
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文」を参照してください。
例5-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.
例5-5 単純なCASE文をシミュレートするIF THEN ELSIF文
この例では、IF
THEN
ELSIF
文を多数のELSIF
句とともに使用し、単一の値を多くの使用可能な値と比較しています。この目的では、単純なCASE
文の方がより明確になります(例5-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
単純なCASE文
単純なCASE
文の構造は、次のとおりです。
CASE selector
WHEN { selector_value_1a | dangling_predicate_1a }
[, …, { selector_value_1n | dangling_predicate_1n }] THEN statements_1
WHEN { selector_value_2a | dangling_predicate_2a }
[, …, { selector_value_2n | dangling_predicate_2n }] THEN statements_2
...
WHEN { selector_value_na | dangling_predicate_na }
[, …, { selector_value_nn | dangling_predicate_nn }] THEN statements_n
[ ELSE
else_statements ]
END CASE;
selector
は式です(通常は1つの変数)。各selector_value
はリテラルまたは式のいずれかです。dangling_predicate
は、1つまたは複数のselector_value
のかわりに、またはこれらを組み合せて使用することもできます。(構文の詳細は、「CASE文」を参照してください。)
dangling_predicate
は、左オペランドが欠落している通常の式です(例:, < 2
)。dangling_predicate
を使用すると、検索対象のCASE
文を必要とするより複雑な比較が可能になります。
単純なCASE
文では、selector_value
がselector
と等しいか、dangling_predicate
がtrue
である最初のstatements
が実行されます。残りの条件は評価されません。selector
と等しいselector_value
がなく、true
のdangling_predicate
がない場合、else_statements
が存在する場合は、CASE
文でそれらが実行されますが、存在しない場合は、事前定義済の例外CASE_NOT_FOUND
が発生します。
例5-6では、単純なCASE
文を使用して、単一の値を多くの使用可能な値と比較しています。例5-6のCASE
文は、例5-5のIF
THEN
ELSIF
文と論理的に等価です。
ノート:
単純なCASE
式と同様に、単純なCASE
文の選択子の値がNULL
の場合、その選択子がWHEN
NULL
によって一致することはありません(例3-51を参照)。かわりに、検索CASE
文をWHEN
condition
IS
NULL
とともに使用します(例3-55を参照)。
例5-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
例5-7 Dangling Predicateを使用した単純なCASE文
DECLARE grade NUMBER; BEGIN grade := '85'; CASE grade WHEN < 0, > 100 THEN DBMS_OUTPUT.PUT_LINE('No such grade'); WHEN > 89 THEN DBMS_OUTPUT.PUT_LINE('A'); WHEN > 79 THEN DBMS_OUTPUT.PUT_LINE('B'); WHEN > 69 THEN DBMS_OUTPUT.PUT_LINE('C'); WHEN > 59 THEN DBMS_OUTPUT.PUT_LINE('D'); ELSE DBMS_OUTPUT.PUT_LINE('F'); END CASE; END; /
結果:
B
検索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文」を参照してください。)
例5-8の検索CASE
文は、例5-6の単純なCASE
文と論理的に等価です。
例5-8と例5-6のいずれの場合も、ELSE
句をEXCEPTION
部に置き換えることができます。例5-9は、例5-8と論理的に等価です。
例5-8 検索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
例5-9 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