条件付き選択文
条件付き選択文のIFおよびCASEは、データ値の違いに応じて異なる文を実行します。
IF文は、条件に応じて、一連の1つ以上の文を実行またはスキップします。IF文には次の形式があります。
-
IFTHEN -
IFTHENELSE -
IFTHENELSIF
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