式
式は、1つ以上の値、演算子、および値に評価されるSQLファンクションの組合せです。
式は常に1つの値を戻します。単純な式には次のものがあります(複雑度の低い順に示しています)。
-
1つの定数または変数(
a
など) -
単項演算子とその1つのオペランド(
-a
など) -
バイナリ演算子とその2つのオペランド(
a+b
など)
オペランドは、変数、定数、リテラル、演算子、ファンクション起動、プレースホルダ、またはその他の式にすることができます。そのため、式は複雑になる場合があります。式の構文の詳細は、「式」を参照してください。
オペランドのデータ型によって、式のデータ型が決まります。式が評価されるたびに、結果としてそのデータ型の値が1つ得られます。結果のデータ型は、式のデータ型です。
連結演算子
連結演算子(||
)は、ある文字列オペランドを別の文字列オペランドに追加します。
連結演算子は、NULLオペランドを無視します。
連結演算子の構文の詳細は、「character_expression ::=」を参照してください。
例3-28 連結演算子
DECLARE x VARCHAR2(4) := 'suit'; y VARCHAR2(4) := 'case'; BEGIN DBMS_OUTPUT.PUT_LINE (x || y); END; /
結果:
suitcase
例3-29 連結演算子とNULLオペランド
連結演算子は、この例に示すとおり、NULLオペランドを無視します。
BEGIN DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce'); END; /
結果:
applesauce
演算子の優先順位
演算は、単項演算子とオペランド1つか、またはバイナリ演算子とオペランド2つのいずれかです。式内の演算は、演算子の優先順位に応じて評価されます。
表3-3に、優先順位の高い順に演算子を示します。同じ優先順位の演算子は、特に順序を考慮せずに評価されます。
表3-3 演算子の優先順位
演算子 | 演算 |
---|---|
|
指数 |
|
恒等、否定 |
|
乗算、除算 |
|
加算、減算、連結 |
|
比較 |
|
否定 |
|
論理積 |
|
論理和 |
評価の順序を制御するには、例3-30に示すとおり、演算をカッコで囲みます。
カッコがネストされている場合は、最も深くネストされた演算が最初に評価されます。
カッコが評価の順序に影響しない場合でも、カッコを使用してわかりやすくすることができます。
例3-30 カッコを使用した評価順序の制御
DECLARE
a INTEGER := 1+2**2;
b INTEGER := (1+2)**2;
BEGIN
DBMS_OUTPUT.PUT_LINE('a = ' || TO_CHAR(a));
DBMS_OUTPUT.PUT_LINE('b = ' || TO_CHAR(b));
END;
/
結果:
a = 5 b = 9
例3-31 ネストしたカッコを使用した式
この例では、演算(1+2)および(3+4)が最初に評価され、それぞれ3および7という値が算出されます。次に、演算3*7が評価され、21という結果が算出されます。最後に21/7が評価され、最終的な値として3が算出されます。
DECLARE
a INTEGER := ((1+2)*(3+4))/7;
BEGIN
DBMS_OUTPUT.PUT_LINE('a = ' || TO_CHAR(a));
END;
/
結果:
a = 3
例3-32 カッコを使用した読みやすさの向上
この例では、カッコは評価の順序に影響しません。これらは、わかりやすくするためにのみ使用されます。
DECLARE a INTEGER := 2**2*3**2; b INTEGER := (2**2)*(3**2); BEGIN DBMS_OUTPUT.PUT_LINE('a = ' || TO_CHAR(a)); DBMS_OUTPUT.PUT_LINE('b = ' || TO_CHAR(b)); END; /
結果:
a = 36 b = 36
例3-33 演算子の優先順位
この例では、より複雑ないくつかの式での演算子の優先順位とカッコの効果を示します。
DECLARE salary NUMBER := 60000; commission NUMBER := 0.10; BEGIN -- Division has higher precedence than addition: DBMS_OUTPUT.PUT_LINE('5 + 12 / 4 = ' || TO_CHAR(5 + 12 / 4)); DBMS_OUTPUT.PUT_LINE('12 / 4 + 5 = ' || TO_CHAR(12 / 4 + 5)); -- Parentheses override default operator precedence: DBMS_OUTPUT.PUT_LINE('8 + 6 / 2 = ' || TO_CHAR(8 + 6 / 2)); DBMS_OUTPUT.PUT_LINE('(8 + 6) / 2 = ' || TO_CHAR((8 + 6) / 2)); -- Most deeply nested operation is evaluated first: DBMS_OUTPUT.PUT_LINE('100 + (20 / 5 + (7 - 3)) = ' || TO_CHAR(100 + (20 / 5 + (7 - 3)))); -- Parentheses, even when unnecessary, improve readability: DBMS_OUTPUT.PUT_LINE('(salary * 0.05) + (commission * 0.25) = ' || TO_CHAR((salary * 0.05) + (commission * 0.25)) ); DBMS_OUTPUT.PUT_LINE('salary * 0.05 + commission * 0.25 = ' || TO_CHAR(salary * 0.05 + commission * 0.25) ); END; /
結果:
5 + 12 / 4 = 8 12 / 4 + 5 = 8 8 + 6 / 2 = 11 (8 + 6) / 2 = 7 100 + (20 / 5 + (7 - 3)) = 108 (salary * 0.05) + (commission * 0.25) = 3000.025 salary * 0.05 + commission * 0.25 = 3000.025
論理演算子
論理演算子AND
、OR
、およびNOT
は、3値論理に従います。
AND
とOR
はバイナリ演算子、NOT
は単項演算子です。
表3-4 論理真理値表
x | y | x AND y | x OR y | NOT x |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AND
は、両方のオヘ゜ランドがTRUE
の場合のみ、TRUE
を戻します。
OR
は、どちらか一方のオペランドがTRUE
の場合に、TRUE
を戻します。
NOT
は、オペランドがNULL
の場合を除き、オペランドの反対の値を戻します。NULL
は値を持たないため、NOT
NULL
はNULL
を戻します。
例3-34 BOOLEAN変数を出力するプロシージャ
この例では、BOOLEAN
変数の値を出力するprint_boolean
というプロシージャを作成します。このプロシージャでは、「IS [NOT] NULL演算子」が使用されます。この章で紹介するいくつかの例で、print_boolean
を起動しています。
CREATE OR REPLACE PROCEDURE print_boolean ( b_name VARCHAR2, b_value BOOLEAN ) AUTHID DEFINER IS BEGIN IF b_value IS NULL THEN DBMS_OUTPUT.PUT_LINE (b_name || ' = NULL'); ELSIF b_value = TRUE THEN DBMS_OUTPUT.PUT_LINE (b_name || ' = TRUE'); ELSE DBMS_OUTPUT.PUT_LINE (b_name || ' = FALSE'); END IF; END; /
例3-35 AND演算子
表3-4およびこの例に示すとおり、両方のオペランドがTRUE
である場合にのみ、AND
はTRUE
を戻します。
DECLARE PROCEDURE print_x_and_y ( x BOOLEAN, y BOOLEAN ) IS BEGIN print_boolean ('x', x); print_boolean ('y', y); print_boolean ('x AND y', x AND y); END print_x_and_y; BEGIN print_x_and_y (FALSE, FALSE); print_x_and_y (TRUE, FALSE); print_x_and_y (FALSE, TRUE); print_x_and_y (TRUE, TRUE); print_x_and_y (TRUE, NULL); print_x_and_y (FALSE, NULL); print_x_and_y (NULL, TRUE); print_x_and_y (NULL, FALSE); END; /
結果:
x = FALSE y = FALSE x AND y = FALSE x = TRUE y = FALSE x AND y = FALSE x = FALSE y = TRUE x AND y = FALSE x = TRUE y = TRUE x AND y = TRUE x = TRUE y = NULL x AND y = NULL x = FALSE y = NULL x AND y = FALSE x = NULL y = TRUE x AND y = NULL x = NULL y = FALSE x AND y = FALSE
例3-36 OR演算子
表3-4およびこの例に示すとおり、一方のオペランドがTRUE
である場合、OR
はTRUE
を戻します。(この例は、例3-34のprint_boolean
プロシージャを起動します)。
DECLARE PROCEDURE print_x_or_y ( x BOOLEAN, y BOOLEAN ) IS BEGIN print_boolean ('x', x); print_boolean ('y', y); print_boolean ('x OR y', x OR y); END print_x_or_y; BEGIN print_x_or_y (FALSE, FALSE); print_x_or_y (TRUE, FALSE); print_x_or_y (FALSE, TRUE); print_x_or_y (TRUE, TRUE); print_x_or_y (TRUE, NULL); print_x_or_y (FALSE, NULL); print_x_or_y (NULL, TRUE); print_x_or_y (NULL, FALSE); END; /
結果:
x = FALSE y = FALSE x OR y = FALSE x = TRUE y = FALSE x OR y = TRUE x = FALSE y = TRUE x OR y = TRUE x = TRUE y = TRUE x OR y = TRUE x = TRUE y = NULL x OR y = TRUE x = FALSE y = NULL x OR y = NULL x = NULL y = TRUE x OR y = TRUE x = NULL y = FALSE x OR y = NULL
例3-37 NOT演算子
表3-4およびこの例に示すとおり、オペランドがNULL
でないかぎり、NOT
はオペランドの反対の値を戻します。NULL
は値を持たないため、NOT
NULL
はNULL
を戻します。(この例は、例3-34のprint_boolean
プロシージャを起動します)。
DECLARE PROCEDURE print_not_x ( x BOOLEAN ) IS BEGIN print_boolean ('x', x); print_boolean ('NOT x', NOT x); END print_not_x; BEGIN print_not_x (TRUE); print_not_x (FALSE); print_not_x (NULL); END; /
結果:
x = TRUE NOT x = FALSE x = FALSE NOT x = TRUE x = NULL NOT x = NULL
例3-38 等しくない比較でのNULL値
この例では、x
とy
が等しくないため、一連の文が実行されることが予測されます。ただし、NULL
値は予測不可能です。そのため、x
とy
が等しいかどうかは不明です。したがって、IF
条件はNULL
になり、一連の文は実行されずにバイパスされます。
DECLARE x NUMBER := 5; y NUMBER := NULL; BEGIN IF x != y THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('x != y'); -- not run ELSIF x = y THEN -- also yields NULL DBMS_OUTPUT.PUT_LINE('x = y'); ELSE DBMS_OUTPUT.PUT_LINE ('Can''t tell if x and y are equal or not.'); END IF; END; /
結果:
Can't tell if x and y are equal or not.
例3-39 等しい比較でのNULL値
この例では、a
とb
が等しいため、一連の文が実行されることが予測されます。ただし、等号条件が成立するかどうかは不明であるため、IF
条件はNULL
になり、一連の文は実行されずにバイパスされます。
DECLARE a NUMBER := NULL; b NUMBER := NULL; BEGIN IF a = b THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('a = b'); -- not run ELSIF a != b THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('a != b'); -- not run ELSE DBMS_OUTPUT.PUT_LINE('Can''t tell if two NULLs are equal'); END IF; END; /
結果:
Can't tell if two NULLs are equal
例3-40 NULLと等しいNOT NULL
この例では、2つのIF
文は等しく見えます。ただし、x
とy
のどちらかがNULL
の場合、1番目のIF
文はy
の値をhigh
に代入しますが、2番目のIF
文はx
の値をhigh
に代入します。
DECLARE x INTEGER := 2; Y INTEGER := 5; high INTEGER; BEGIN IF (x > y) -- If x or y is NULL, then (x > y) is NULL THEN high := x; -- run if (x > y) is TRUE ELSE high := y; -- run if (x > y) is FALSE or NULL END IF; IF NOT (x > y) -- If x or y is NULL, then NOT (x > y) is NULL THEN high := y; -- run if NOT (x > y) is TRUE ELSE high := x; -- run if NOT (x > y) is FALSE or NULL END IF; END; /
例3-41 論理演算子の演算順序の変更
この例では、例3-34のprint_boolean
プロシージャを3回起動します。3回目と1回目の起動は論理的に等しく、3回目の起動は読みやすさを向上させただけです。2番目の起動では、カッコによって演算の順序が変更されています。
DECLARE x BOOLEAN := FALSE; y BOOLEAN := FALSE; BEGIN print_boolean ('NOT x AND y', NOT x AND y); print_boolean ('NOT (x AND y)', NOT (x AND y)); print_boolean ('(NOT x) AND y', (NOT x) AND y); END; /
結果:
NOT x AND y = FALSE NOT (x AND y) = TRUE (NOT x) AND y = FALSE
短絡評価
論理式を評価するときに、PL/SQLでは短絡評価を使用します。これによって、PL/SQLは結果が判別できた時点でただちに式の評価を停止します。
そのため、評価を続ければエラーになるような式でも書くことができます。
例3-42では、OR
式で0(ゼロ)による除算エラーが発生するのを短絡評価によって回避しています。on_hand
の値が0(ゼロ)の場合、左のオペランドはTRUE
になるため、PL/SQLは右のオペランドを評価しません。PL/SQLによりOR
演算子を適用する前に両方のオペランドを評価した場合には、右のオペランドは0による除算エラーになります。
例3-42 短絡評価
DECLARE
on_hand INTEGER := 0;
on_order INTEGER := 100;
BEGIN
-- Does not cause divide-by-zero error;
-- evaluation stops after first expression
IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN
DBMS_OUTPUT.PUT_LINE('On hand quantity is zero.');
END IF;
END;
/
結果:
On hand quantity is zero.
比較演算子
比較演算子は式と式を比較します。比較の結果は、常にTRUE
、FALSE
またはNULL
のいずれかです。
一方の式の値がNULL
の場合、比較の結果もNULL
になります。
比較演算子は、次のとおりです。
ノート:
文字の比較は、実行時に変更可能なNLSパラメータ設定に影響を受けます。したがって、文字の比較は実行時に評価されるので、同じ文字の比較を行っても、タイミングによっては異なる値になることがあります。文字の比較に影響するNLSパラメータの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
ノート:
比較演算子にCLOB
値を使用すると、一時的なLOB値が作成される場合があります。一時表領域がこのような値を処理できる大きさであることを確認してください。
関係演算子
この表は、関係演算子の概要を示しています。
表3-5 関係演算子
演算子 | 意味 |
---|---|
|
等しい |
|
等しくない |
|
次より小さい |
|
次より大きい |
|
<= |
|
以上または同等 |
ここでのトピック
算術比較
片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。
実数は近似値として格納されるため、等しいかどうかの比較をすることをお薦めします。
例3-43 式での関係演算子
この例では、例3-35のprint_boolean
プロシージャを起動し、関係演算子を使用して算術値を比較する式の値を出力します。
BEGIN print_boolean ('(2 + 2 = 4)', 2 + 2 = 4); print_boolean ('(2 + 2 <> 4)', 2 + 2 <> 4); print_boolean ('(2 + 2 != 4)', 2 + 2 != 4); print_boolean ('(2 + 2 ~= 4)', 2 + 2 ~= 4); print_boolean ('(2 + 2 ^= 4)', 2 + 2 ^= 4); print_boolean ('(1 < 2)', 1 < 2); print_boolean ('(1 > 2)', 1 > 2); print_boolean ('(1 <= 2)', 1 <= 2); print_boolean ('(1 >= 1)', 1 >= 1); END; /
結果:
(2 + 2 = 4) = TRUE (2 + 2 <> 4) = FALSE (2 + 2 != 4) = FALSE (2 + 2 ~= 4) = FALSE (2 + 2 ^= 4) = FALSE (1 < 2) = TRUE (1 > 2) = FALSE (1 <= 2) = TRUE (1 >= 1) = TRUE
文字比較
デフォルトでは、片方の文字のバイナリ値がより大きい場合、その文字はより大きいとみなされます。
たとえば、次の式はTRUEになります。
'y' > 'r'
文字列は文字ごとに比較されます。たとえば、次の式はTRUEになります。
'Kathy' > 'Kathryn'
初期化パラメータNLS_COMP=ANSI
を設定すると、NLS_SORT
初期化パラメータで指定された照合順番が文字列比較に使用されます。
照合順番とは、特定の範囲の数値コードが個々の文字に対応している文字セットの内部的な順序のことです。内部的な順番を表す数値が他方の文字より大きい場合、その文字値はより大きいとみなされます。この種の文字が照合順番に使用される場所については、言語ごとに規則が異なる場合があります。たとえば、アクセント記号が付いた文字のソート順序は、バイナリ値が同じであってもデータベース文字セットに応じて異なることがあります。
NLS_SORT
パラメータの値を変更すると、大/小文字およびアクセント記号の有無を区別しない比較を実行できます。
大/小文字を区別しない比較では、対応する大文字と小文字が同じ文字として扱われます。たとえば、次の式はTRUEになります。
'a' = 'A' 'Alpha' = 'ALPHA'
大/小文字を区別せずに比較するには、NLS_SORT
パラメータの値の末尾に_CI
を付けます(BINARY_CI
やXGERMAN_CI
など)。
アクセント記号の有無を区別しない比較では、大/小文字が区別されず、アクセント記号またはデリミタ文字のみが異なる文字も、同じ文字として扱われます。たとえば、次の式はTRUEになります。
'Cooperate' = 'Co-Operate' 'Co-Operate' = 'coöperate'
大/小文字およびアクセント記号の有無のいずれも区別せずに比較するには、NLS_SORT
パラメータの値の末尾に_AI
を付けます(BINARY_AI
やFRENCH_M_AI
など)。
CHAR
データ型とVARCHAR2
データ型のセマンティックの違いは、文字の比較に影響します。
詳細は、「値の比較」を参照してください。
LIKE演算子
LIKE
演算子は、文字、文字列またはCLOB
値をパターンと比較し、値がパターンと一致した場合はTRUE
、一致しなかった場合はFALSE
を戻します。
大/小文字が区別されます。
パターンには、アンダースコア(_)およびパーセント記号(%)の2種類のワイルドカード文字を使用できます。
アンダースコアは1つの文字を表します。
パーセント記号(%
)は0(ゼロ)個以上の文字を表します。
パーセント記号やアンダースコアを検索するには、エスケープ文字を定義して、パーセント記号またはアンダースコアの前にそのエスケープ文字を挿入します。
関連項目:
-
LIKE
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 -
LIKE
と類似したREGEXP_LIKE
の使用の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
例3-44 式でのLIKE演算子
この例に示すように、文字列'Johnson'
はパターン'J%s_n'
に一致しますが、'J%S_N'
には一致しません。
DECLARE
PROCEDURE compare (
value VARCHAR2,
pattern VARCHAR2
) IS
BEGIN
IF value LIKE pattern THEN
DBMS_OUTPUT.PUT_LINE ('TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE ('FALSE');
END IF;
END;
BEGIN
compare('Johnson', 'J%s_n');
compare('Johnson', 'J%S_N');
END;
/
結果:
TRUE FALSE
例3-45 パターン内のエスケープ文字
この例では、バックスラッシュをエスケープ文字として使用しているため、文字列内のパーセント記号はワイルドカードとしては機能しません。
DECLARE
PROCEDURE half_off (sale_sign VARCHAR2) IS
BEGIN
IF sale_sign LIKE '50\% off!' ESCAPE '\' THEN
DBMS_OUTPUT.PUT_LINE ('TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE ('FALSE');
END IF;
END;
BEGIN
half_off('Going out of business!');
half_off('50% off!');
END;
/
結果:
FALSE TRUE
BETWEEN演算子
BETWEEN
演算子は、値が指定した範囲内にあるかどうかをテストします。
式x BETWEEN a AND b
の値は、式(x>=a) AND (x<=b)
の値と同じものとして定義されます。式x
は1回のみ評価されます。
関連項目:
BETWEEN
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
例3-46 式でのBETWEEN演算子
この例では、例3-34のprint_boolean
プロシージャを起動し、BETWEEN
演算子を含む式の値を出力します。
BEGIN print_boolean ('2 BETWEEN 1 AND 3', 2 BETWEEN 1 AND 3); print_boolean ('2 BETWEEN 2 AND 3', 2 BETWEEN 2 AND 3); print_boolean ('2 BETWEEN 1 AND 2', 2 BETWEEN 1 AND 2); print_boolean ('2 BETWEEN 3 AND 4', 2 BETWEEN 3 AND 4); END; /
結果:
2 BETWEEN 1 AND 3 = TRUE2 BETWEEN 2 AND 3 = TRUE
2 BETWEEN 1 AND 2 = TRUE
2 BETWEEN 3 AND 4 = FALSE
IN演算子
IN
演算子は、セット・メンバーシップをテストします。
x
IN
(
set
)
は、x
がset
のメンバーに等しい場合にのみTRUE
を戻します。
関連項目:
IN
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
例3-47 式でのIN演算子
この例では、例3-34のprint_boolean
プロシージャを起動し、IN
演算子を含む式の値を出力します。
DECLARE letter VARCHAR2(1) := 'm'; BEGIN print_boolean ( 'letter IN (''a'', ''b'', ''c'')', letter IN ('a', 'b', 'c') ); print_boolean ( 'letter IN (''z'', ''m'', ''y'', ''p'')', letter IN ('z', 'm', 'y', 'p') ); END; /
結果:
letter IN ('a', 'b', 'c') = FALSE letter IN ('z', 'm', 'y', 'p') = TRUE
例3-48 NULL値を含む集合でのIN演算子
この例は、set
にNULL
値が含まれている場合に発生する状況を示しています。これは、例3-34のprint_boolean
プロシージャを起動します。
DECLARE a INTEGER; -- Initialized to NULL by default b INTEGER := 10; c INTEGER := 100; BEGIN print_boolean ('100 IN (a, b, c)', 100 IN (a, b, c)); print_boolean ('100 NOT IN (a, b, c)', 100 NOT IN (a, b, c)); print_boolean ('100 IN (a, b)', 100 IN (a, b)); print_boolean ('100 NOT IN (a, b)', 100 NOT IN (a, b)); print_boolean ('a IN (a, b)', a IN (a, b)); print_boolean ('a NOT IN (a, b)', a NOT IN (a, b)); END; /
結果:
100 IN (a, b, c) = TRUE 100 NOT IN (a, b, c) = FALSE 100 IN (a, b) = NULL 100 NOT IN (a, b) = NULL a IN (a, b) = NULL a NOT IN (a, b) = NULL
BOOLEAN式
BOOLEAN
式とは、BOOLEAN
値(TRUE
、FALSE
またはNULL
)を戻す式のことです。
最も単純なBOOLEAN
式は、1個のBOOLEAN
リテラル、定数または変数です。次のものもBOOLEAN
式です。
NOT boolean_expression boolean_expression relational_operator boolean_expression boolean_expression { AND | OR } boolean_expression
関係演算子のリストは、表3-5を参照してください。BOOLEAN
式の構文の詳細は、「boolean_expression ::=」を参照してください。
通常、BOOLEAN
式は、制御文(「PL/SQLの制御文」を参照)およびDML文のWHERE
句で条件として使用します。
BOOLEAN
変数自体を条件として使用できますが、TRUE
値またはFALSE
値と比較する必要はありません。
例3-49 等価なBOOLEAN式
この例では、ループの条件は等価です。
DECLARE done BOOLEAN; BEGIN -- These WHILE loops are equivalent done := FALSE; WHILE done = FALSE LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT (done = TRUE) LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT done LOOP done := TRUE; END LOOP; END; /
CASE式
単純なCASE式
この説明では、単純なCASE
式の構文が次のような構文であるとします。
CASE selector
WHEN { selector_value_1a | dangling_predicate_1a }
[ , ..., { selector_value_1n | dangling_predicate_1n } ] THEN result_1
WHEN { selector_value_2a | dangling_predicate_2a }
[ , ..., { selector_value_2n | dangling_predicate_2n } ] THEN result_2
...
WHEN { selector_value_na | dangling_predicate_na }
[ , ..., { selector_value_nn | dangling_predicate_nn }] THEN result_n
[ ELSE
else_result ]
END;
selector
は式です(通常は1つの変数)。selector_value
とresult
は、それぞれリテラルまたは式にすることができます。dangling_predicate
は、1つまたは複数のselector_value
のかわりに、またはこれらを組み合せて使用することもできます。少なくとも1つのresult
はリテラルのNULL
ではない必要があります。
dangling_predicate
は、左オペランドが欠落している通常の式です(例: < 2
)。dangling_predicate
を使用すると、検索対象のCASE
文を必要とするより複雑な比較が可能になります。
単純なCASE
式は、selector_value
またはdangling_predicate
がselector
と一致した最初のresult
を戻します。残りの式は評価されません。selector
と一致するselector_value
またはdangling_predicate
がない場合、CASE
式は、else_result
が存在するとそれを返し、存在しないとNULL
を返します。
複数の選択肢が単一のresult
にマップされている場合、カンマ区切りのselector_value
またはdangling_predicate
(あるいはその両方)のリストを各WHEN
句で使用できます。個別のWHEN
句にリストされているselector_value
およびdangling_predicate
と同様に、selector
と一致する最初のselector_value
またはdangling_predicate
のみが評価されます。
関連項目:
構文の詳細は、「simple_case_expression ::=」を参照してください
例3-50 単純なCASE式
この例では、単純なCASE
式の値を変数appraisal
に代入します。selector
はgrade
です。
DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(20); BEGIN appraisal := CASE grade WHEN 'A' THEN 'Excellent' WHEN 'B' THEN 'Very Good' WHEN 'C' THEN 'Good' WHEN 'D' THEN 'Fair' WHEN 'F' THEN 'Poor' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE ('Grade ' || grade || ' is ' || appraisal); END; /
結果:
Grade B is Very Good
例3-51 WHEN NULLを使用した単純なCASE式
この例に示すように、selector
の値がNULL
の場合、WHEN
NULL
では一致させることができません。
かわりに、例3-55に示すように、検索CASE
式をWHEN
boolean_expression
IS
NULL
とともに使用します。
DECLARE grade CHAR(1); -- NULL by default appraisal VARCHAR2(20); BEGIN appraisal := CASE grade WHEN NULL THEN 'No grade assigned' WHEN 'A' THEN 'Excellent' WHEN 'B' THEN 'Very Good' WHEN 'C' THEN 'Good' WHEN 'D' THEN 'Fair' WHEN 'F' THEN 'Poor' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE ('Grade ' || grade || ' is ' || appraisal); END; /
結果:
Grade is No such grade
例3-52 selector_valueのリストを使用した単純なCASE式
DECLARE
salary NUMBER := 7000;
salary_level VARCHAR2(20);
BEGIN
salary_level :=
CASE salary
WHEN 1000, 2000 THEN 'low'
WHEN 3000, 4000, 5000 THEN 'normal'
WHEN 6000, 7000, 8000 THEN 'high'
ELSE 'executive pay'
END;
DBMS_OUTPUT.PUT_LINE('Salary level is: ' || salary_level);
END;
/
結果:
Salary level is: high
例3-53 Dangling Predicateを使用した単純なCASE式
data_val/2
の値は、dangling_predicate
の評価中に左側のオペランドとして使用されます。この状況で検索されたCASE
式ではなく単純なCASE
式を使用すると、selector
式の繰返し計算を回避できます。条件のリストは、selector_value
とdangling_predicate
の任意の組合せで使用できます。
DECLARE
data_val NUMBER := 30;
status VARCHAR2(20);
BEGIN
status :=
CASE data_val/2
WHEN < 0, > 50 THEN 'outlier'
WHEN BETWEEN 10 AND 30 THEN 'good'
ELSE 'bad'
END;
DBMS_OUTPUT.PUT_LINE('The data status is: ' || status);
END;
/
結果:
The data status is: good
検索CASE式
この説明では、検索CASE
式の構文は次のような構文であるとします。
CASE WHEN boolean_expression_1 THEN result_1 WHEN boolean_expression_2 THEN result_2 ... WHEN boolean_expression_n THEN result_n [ ELSE else_result ] END]
検索CASE
式は、boolean_expression
がTRUE
になる最初のresult
を戻します。残りの式は評価されません。TRUE
になるboolean_expression
がない場合、CASE
式は、else_result
が存在するとそれを戻し、存在しないとNULL
を戻します。
関連項目:
構文の詳細は、「searched_case_expression ::=」を参照してください
例3-54 検索CASE式
この例では、検索CASE
式の値を変数appraisal
に代入します。
DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(120); id NUMBER := 8429862; attendance NUMBER := 150; min_days CONSTANT NUMBER := 200; FUNCTION attends_this_school (id NUMBER) RETURN BOOLEAN IS BEGIN RETURN TRUE; END; BEGIN appraisal := CASE WHEN attends_this_school(id) = FALSE THEN 'Student not enrolled' WHEN grade = 'F' OR attendance < min_days THEN 'Poor (poor performance or bad attendance)' WHEN grade = 'A' THEN 'Excellent' WHEN grade = 'B' THEN 'Very Good' WHEN grade = 'C' THEN 'Good' WHEN grade = 'D' THEN 'Fair' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE ('Result for student ' || id || ' is ' || appraisal); END; /
結果:
Result for student 8429862 is Poor (poor performance or bad attendance)
例3-55 WHEN ... IS NULLを使用した検索CASE式
この例では、検索CASE
式を使用して、例3-51の問題を解決します。
DECLARE grade CHAR(1); -- NULL by default appraisal VARCHAR2(20); BEGIN appraisal := CASE WHEN grade IS NULL THEN 'No grade assigned' WHEN grade = 'A' THEN 'Excellent' WHEN grade = 'B' THEN 'Very Good' WHEN grade = 'C' THEN 'Good' WHEN grade = 'D' THEN 'Fair' WHEN grade = 'F' THEN 'Poor' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE ('Grade ' || grade || ' is ' || appraisal); END; /
結果:
Grade is No grade assigned
PL/SQL式でのSQLファンクション
PL/SQL式では、次のファンクションを除くすべてのSQLファンクションを使用できます。
-
集計ファンクション(
AVG
、COUNT
など) -
集約ファンクション
JSON_ARRAYAGG
-
集約ファンクション
JSON_DATAGUIDE
-
集約ファンクション
JSON_MERGEPATCH
-
集約ファンクション
JSON_OBJECTAGG
-
JSON_TABLE
-
JSON_TRANSFORM
-
JSON条件
JSON_TEXTCONTAINS
-
分析ファンクション(
LAG
、RATIO_TO_REPORT
など) -
変換ファンクション
BIN_TO_NUM
-
データ・マイニング・ファンクション(
CLUSTER_ID
、FEATURE_VALUE
など) -
エンコーディング・ファンクションおよびデコーディング・ファンクション(
DECODE
、DUMP
など) -
モデル・ファンクション(
ITERATION_NUMBER
、PREVIOUS
など) -
オブジェクト参照ファンクション(
REF
、VALUE
など) -
XMLファンクション
-
次の照合SQL演算子およびファンクション:
-
COLLATE
演算子 -
COLLATION
ファンクション -
NLS_COLLATION_ID
ファンクション -
NLS_COLLATION_NAME
ファンクション
-
-
その他の該当するファンクション:
-
CUBE_TABLE
-
DATAOBJ_TO_PARTITION
-
LNNVL
-
SYS_CONNECT_BY_PATH
-
SYS_TYPEID
-
WIDTH_BUCKET
-
PL/SQLでは、引数および結果がBINARY_INTEGER
であるBITAND
のオーバーロードがサポートされています。
PL/SQL式でRAWTOHEX
ファンクションを使用すると、データ型RAW
の引数が受け入れられ、その引数の値を構成するバイトの16進表現でVARCHAR2
値が戻されます。RAW
以外の型の引数は、RAW
に暗黙的に変換できる場合にのみ指定できます。この変換は、HEXTORAW
ファンクションの有効な引数であるCHAR
、VARCHAR2
およびLONG
の値と、最大16380バイトのLONG
RAW
およびBLOB
の値に対して実行可能です。
静的な式
静的な式は、値がコンパイル時に決定される式です。文字の比較、変数またはファンクションの起動は含まれていません。静的な式は、条件付きコンパイル・ディレクティブで使用できる唯一の式です。
静的な式の定義
-
式がNULLリテラルである場合、その式は静的です。
-
式が文字、数値またはブールのリテラルである場合、その式は静的です。
-
式が静的定数への参照である場合、その式は静的です。
-
式が$$で始まる条件付きコンパイル変数への参照である場合、その式は静的です。
-
演算子が静的な式で許可されていて、そのオペランドがすべて静的であり、そのオペランドに対する評価時に演算子による例外が発生しない場合、その式は静的です。
表3-6 静的な式で許可される演算子
演算子 | 演算子のカテゴリ |
---|---|
() |
式のデリミタ |
** |
指数 |
*, /,+, - |
除算、乗算、加算(または正)、減算(または負)の算術演算子 |
=, !=, <, <=, >=, > IS [NOT] NULL |
比較演算子 |
NOT |
論理演算子 |
[NOT] LIKE, [NOT] LIKE2, [NOT] LIKE4, [NOT] LIKEC |
パターン一致演算子 |
XOR |
二項演算子 |
このリストに、静的な式で許可されるファンクションを示します。
-
ABS
-
ACOS
-
ASCII
-
ASCIISTR
-
ASIN
-
ATAN
-
ATAN2
-
BITAND
-
CEIL
-
CHR
-
COMPOSE
-
CONVERT
-
COS
-
COSH
-
DECOMPOSE
-
EXP
-
FLOOR
-
HEXTORAW
-
INSTR
-
INSTRB
-
INSTRC
-
INSTR2
-
INSTR4
-
IS [NOT] INFINITE
-
IS [NOT] NAN
-
LENGTH
-
LENGTH2
-
LENGTH4
-
LENGTHB
-
LENGTHC
-
LN
-
LOG
-
LOWER
-
LPAD
-
LTRIM
-
MOD
-
NVL
-
POWER
-
RAWTOHEX
-
REM
-
REMAINDER
-
REPLACE
-
ROUND
-
RPAD
-
RTRIM
-
SIGN
-
SIN
-
SINH
-
SQRT
-
SUBSTR
-
SUBSTR2
-
SUBSTR4
-
SUBSTRB
-
SUBSTRC
-
TAN
-
TANH
-
TO_BINARY_DOUBLE
-
TO_BINARY_FLOAT
-
TO_BOOLEAN
-
TO_CHAR
-
TO_NUMBER
-
TRIM
-
TRUNC
-
UPPER
静的な式は、次のサブタイプの宣言で使用できます。
-
文字列型(
VARCHAR2、NCHAR、CHAR、NVARCHAR2、RAW
、およびANSIの同等の型)の長さ -
NUMBER
型およびサブタイプ(FLOAT
など)の位取りおよび精度 -
期間型の精度(年、月、秒)
-
時刻およびタイムスタンプの精度
-
VARRAY
の境界 -
型の宣言における範囲の境界
いずれの場合も、静的な式の結果の型は、宣言された項目のサブタイプと同じであることに加え、コンテキストに対して適切な範囲にある必要があります。
静的なPLS_INTEGER式
静的なPLS_INTEGER
式には次のものがあります。
関連項目:
PLS_INTEGER
データ型の詳細は、「PLS_INTEGERおよびBINARY_INTEGERデータ型」を参照してください
静的なBOOLEAN式
静的なBOOLEAN
式には次のものがあります。
-
BOOLEAN
リテラル(TRUE
、FALSE
またはNULL
) -
BOOLEAN
静的定数静的定数の詳細は、「静的定数」を参照してください。
-
x
およびy
は、静的なPLS_INTEGER
式です。-
x
>
y
-
x
<
y
-
x
>=
y
-
x
<=
y
-
x
=
y
-
x
<>
y
静的な
PLS_INTEGER
式の詳細は、「静的なPLS_INTEGER式」を参照してください。 -
-
x
およびy
はBOOLEAN
式です。-
NOT
y
-
x
AND
y
-
x
OR
y
-
x
>
y
-
x
>=
y
-
x
=
y
-
x
<=
y
-
x
<>
y
静的な
BOOLEAN
式の詳細は、「ブール式」を参照してください。 -
-
x
は静的な式です。-
x
IS
NULL
-
x
IS
NOT
NULL
静的な式の詳細は、「静的な式」を参照してください。
-
関連項目:
BOOLEAN
データ型の詳細は、「ブール・データ型」を参照してください
静的なVARCHAR2式
静的なVARCHAR2
式には次のものがあります。
-
最大サイズが32,767バイトである文字列リテラル
リテラルの詳細は、「リテラル」を参照してください。
-
NULL
-
TO_CHAR(x)
(x
は静的なPLS_INTEGER
式)TO_CHAR
ファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 -
TO_CHAR(x
,f
,n)
(x
は静的なPLS_INTEGER
式で、f
とn
は静的なVARCHAR2
式)TO_CHAR
ファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 -
x
||
y
(x
およびy
は、静的なVARCHAR2
式またはPLS_INTEGER
式)静的な
PLS_INTEGER
式の詳細は、「静的なPLS_INTEGER式」を参照してください。
関連項目:
VARCHAR2
データ型の詳細は、「CHARおよびVARCHAR2変数」を参照してください
静的定数
静的定数は、パッケージ仕様部で次の構文を使用して宣言します。
constant_name CONSTANT data_type := static_expression;
static_expression
の型は、data_type
(BOOLEAN
またはPLS_INTEGER
)と同じである必要があります。
静的定数は、package_name
パッケージの本体内にある場合でも、常にpackage_name
.constant_name
として参照する必要があります。
PL/SQLユニットの条件付きコンパイル・ディレクティブのBOOLEAN
式でconstant_name
を使用する場合、そのPL/SQLユニットはパッケージpackage_name
に依存します。パッケージ仕様部を変更すると、依存するPL/SQLユニットは無効になり、再コンパイルが必要になる場合があります(依存オブジェクトの無効化の詳細は、『Oracle Database開発ガイド』を参照)。
複数のPL/SQLユニットの条件付きコンパイルを制御する静的定数を持つパッケージを使用する場合は、パッケージ仕様部のみを作成し、そのパッケージ仕様部を条件付きコンパイルの制御専用にすることをお薦めします。この方法で、パッケージ仕様部の変更による無効化が最小限に抑えられます。
単一のPL/SQLユニットの条件付きコンパイルを制御する場合は、PLSQL_CCFLAGS
コンパイル・パラメータにフラグを設定できます。このパラメータの詳細は、「問合せディレクティブへの値の代入」および『Oracle Databaseリファレンス』を参照してください。
関連項目:
-
定数の宣言の一般情報は、「定数の宣言」を参照してください
-
パッケージの詳細は、「PL/SQLパッケージ」を参照してください
-
スキーマ・オブジェクトの依存性の詳細は、『Oracle Database開発ガイド』を参照してください。
例3-56 静的定数
この例では、パッケージmy_debug
で静的定数debug
およびtrace
を定義し、複数のPL/SQLユニットでのデバッグおよびトレースを制御します。プロシージャmy_proc1
ではdebug
のみが使用され、プロシージャmy_proc2
ではtrace
のみが使用されますが、いずれのプロシージャもこのパッケージに依存しています。ただし、再コンパイルされるコードが異ならない場合もあります。たとえば、debug
の値をFALSE
に変更しただけで2つのプロシージャを再コンパイルすると、my_proc1
でコンパイルされるコードは変更されますが、my_proc2
でコンパイルされるコードは変更されません。
CREATE PACKAGE my_debug IS debug CONSTANT BOOLEAN := TRUE; trace CONSTANT BOOLEAN := TRUE; END my_debug; / CREATE PROCEDURE my_proc1 AUTHID DEFINER IS BEGIN $IF my_debug.debug $THEN DBMS_OUTPUT.put_line('Debugging ON'); $ELSE DBMS_OUTPUT.put_line('Debugging OFF'); $END END my_proc1; / CREATE PROCEDURE my_proc2 AUTHID DEFINER IS BEGIN $IF my_debug.trace $THEN DBMS_OUTPUT.put_line('Tracing ON'); $ELSE DBMS_OUTPUT.put_line('Tracing OFF'); $END END my_proc2; /