4.1 条件付き選択文
条件付き選択文のIFおよびCASEは、データ値の違いに応じて異なる文を実行します。
IF文は、条件に応じて、一連の1つ以上の文を実行またはスキップします。IF文には次の形式があります。
-
IFTHEN -
IFTHENELSE -
IFTHENELSIF
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変数は、TRUE、FALSE、NULLのいずれかです。次のようには記述しないでください:
IF overdrawn = TRUE THEN RAISE insufficient_funds; END IF;
かわりに、次のように記述してください:
IF overdrawn THEN RAISE insufficient_funds; END IF;
例4-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.
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より大きい場合にのみ、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
例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_valueがselectorと等しい最初のstatementsを実行します。残りの条件は評価されません。いずれのselector_valueもselectorと等しくない場合、CASE文はelse_statements(存在する場合)を実行しますが、else_statementsが存在しない場合は、事前定義の例外CASE_NOT_FOUNDを呼び出します。
例4-6では、単純なCASE文を使用して、単一の値を多くの使用可能な値と比較しています。例4-6のCASE文は、例4-5のIF 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