式は、1つ以上の値、演算子、および値に評価されるSQLファンクションの組合せです。

式は常に1つの値を戻します。単純な式には次のものがあります(複雑度の低い順に示しています)。

  1. 1つの定数または変数(aなど)

  2. 単項演算子とその1つのオペランド(-aなど)

  3. バイナリ演算子とその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 演算子の優先順位

演算子 演算

**

指数

+, -

恒等、否定

*, /

乗算、除算

+, -, ||

加算、減算、連結

=<><=>=<>!=~= ^=IS NULLLIKEBETWEENIN

比較

NOT

否定

AND

論理積

OR

論理和

評価の順序を制御するには、例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

論理演算子

論理演算子ANDOR、およびNOTは、3値論理に従います。

ANDORはバイナリ演算子、NOTは単項演算子です。

表3-4 論理真理値表

x y x AND y x OR y NOT x

TRUE

TRUE

TRUE

TRUE

FALSE

TRUE

FALSE

FALSE

TRUE

FALSE

TRUE

NULL

NULL

TRUE

FALSE

FALSE

TRUE

FALSE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

NULL

FALSE

NULL

TRUE

NULL

TRUE

NULL

TRUE

NULL

NULL

FALSE

FALSE

NULL

NULL

NULL

NULL

NULL

NULL

NULL

ANDは、両方のオヘ゜ランドがTRUEの場合のみ、TRUEを戻します。

ORは、どちらか一方のオペランドがTRUEの場合に、TRUEを戻します。

NOTは、オペランドがNULLの場合を除き、オペランドの反対の値を戻します。NULLは値を持たないため、NOT NULLNULLを戻します。

例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である場合にのみ、ANDTRUEを戻します。

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である場合、ORTRUEを戻します。(この例は、例3-34print_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 NULLNULLを戻します。(この例は、例3-34print_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値

この例では、xyが等しくないため、一連の文が実行されることが予測されます。ただし、NULL値は予測不可能です。そのため、xyが等しいかどうかは不明です。したがって、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値

この例では、abが等しいため、一連の文が実行されることが予測されます。ただし、等号条件が成立するかどうかは不明であるため、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文は等しく見えます。ただし、xyのどちらかが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-34print_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.

比較演算子

比較演算子は式と式を比較します。比較の結果は、常にTRUEFALSEまたはNULLのいずれかです。

一方の式の値がNULLの場合、比較の結果もNULLになります。

比較演算子は、次のとおりです。

ノート:

文字の比較は、実行時に変更可能なNLSパラメータ設定に影響を受けます。したがって、文字の比較は実行時に評価されるので、同じ文字の比較を行っても、タイミングによっては異なる値になることがあります。文字の比較に影響するNLSパラメータの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

ノート:

比較演算子にCLOB値を使用すると、一時的なLOB値が作成される場合があります。一時表領域がこのような値を処理できる大きさであることを確認してください。

IS [NOT] NULL演算子

IS NULL演算子は、オペランドがNULLの場合はBOOLEANTRUEを、NULLではない場合はFALSEを戻します。IS NOT NULL演算子の動作は逆です。

NULL値が関係する比較は、常に結果がNULLになります。

値がNULLかどうかをテストするには、IF value IS NULLを使用します。次の例を参照してください。

  • 例3-14デフォルトでNULLに初期化される変数

  • 例3-34BOOLEAN変数を出力するプロシージャ

  • 例3-55WHEN ... IS NULLを使用した検索CASE式

関係演算子

この表は、関係演算子の概要を示しています。

表3-5 関係演算子

演算子 意味

=

等しい

<>, !=, ~=, ^=

等しくない

<

次より小さい

>

次より大きい

<=

<=

>=

以上または同等

ここでのトピック

算術比較

片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。

実数は近似値として格納されるため、等しいかどうかの比較をすることをお薦めします。

例3-43 式での関係演算子

この例では、例3-35print_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
BOOLEAN比較

定義によれば、TRUEFALSEよりも大きい値を持ちます。NULLとの比較では、NULLが戻されます。

文字比較

デフォルトでは、片方の文字のバイナリ値がより大きい場合、その文字はより大きいとみなされます。

たとえば、次の式はTRUEになります。

'y' > 'r'

文字列は文字ごとに比較されます。たとえば、次の式はTRUEになります。

'Kathy' > 'Kathryn'

初期化パラメータNLS_COMP=ANSIを設定すると、NLS_SORT初期化パラメータで指定された照合順番が文字列比較に使用されます。

照合順番とは、特定の範囲の数値コードが個々の文字に対応している文字セットの内部的な順序のことです。内部的な順番を表す数値が他方の文字より大きい場合、その文字値はより大きいとみなされます。この種の文字が照合順番に使用される場所については、言語ごとに規則が異なる場合があります。たとえば、アクセント記号が付いた文字のソート順序は、バイナリ値が同じであってもデータベース文字セットに応じて異なることがあります。

NLS_SORTパラメータの値を変更すると、大/小文字およびアクセント記号の有無を区別しない比較を実行できます。

大/小文字を区別しない比較では、対応する大文字と小文字が同じ文字として扱われます。たとえば、次の式はTRUEになります。

'a' = 'A'
'Alpha' = 'ALPHA'

大/小文字を区別せずに比較するには、NLS_SORTパラメータの値の末尾に_CIを付けます(BINARY_CIXGERMAN_CIなど)。

アクセント記号の有無を区別しない比較では、大/小文字が区別されず、アクセント記号またはデリミタ文字のみが異なる文字も、同じ文字として扱われます。たとえば、次の式はTRUEになります。

'Cooperate' = 'Co-Operate'
'Co-Operate' = 'coöperate'

大/小文字およびアクセント記号の有無のいずれも区別せずに比較するには、NLS_SORTパラメータの値の末尾に_AIを付けます(BINARY_AIFRENCH_M_AIなど)。

CHARデータ型とVARCHAR2データ型のセマンティックの違いは、文字の比較に影響します。

詳細は、「値の比較」を参照してください。

日付比較

片方の日付がより新しい場合、その日付はより大きいとみなされます。

たとえば、次の式はTRUEになります。

'01-JAN-91' > '31-DEC-90'

LIKE演算子

LIKE演算子は、文字、文字列またはCLOB値をパターンと比較し、値がパターンと一致した場合はTRUE、一致しなかった場合はFALSEを戻します。

大/小文字が区別されます。

パターンには、アンダースコア(_)およびパーセント記号(%)の2種類のワイルドカード文字を使用できます。

アンダースコアは1つの文字を表します。

パーセント記号(%)は0(ゼロ)個以上の文字を表します。

パーセント記号やアンダースコアを検索するには、エスケープ文字を定義して、パーセント記号またはアンダースコアの前にそのエスケープ文字を挿入します。

関連項目:

例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-34print_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 = TRUE
2 BETWEEN 2 AND 3 = TRUE
2 BETWEEN 1 AND 2 = TRUE
2 BETWEEN 3 AND 4 = FALSE

IN演算子

IN演算子は、セット・メンバーシップをテストします。

x IN (set)は、xsetのメンバーに等しい場合にのみTRUEを戻します。

関連項目:

INの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

例3-47 式でのIN演算子

この例では、例3-34print_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演算子

この例は、setNULL値が含まれている場合に発生する状況を示しています。これは、例3-34print_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値(TRUEFALSEまたは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_valueresultは、それぞれリテラルまたは式にすることができます。dangling_predicateは、1つまたは複数のselector_valueのかわりに、またはこれらを組み合せて使用することもできます。少なくとも1つのresultはリテラルのNULLではない必要があります。

dangling_predicateは、左オペランドが欠落している通常の式です(例: < 2)。dangling_predicateを使用すると、検索対象のCASE文を必要とするより複雑な比較が可能になります。

単純なCASE式は、selector_valueまたはdangling_predicateselectorと一致した最初の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に代入します。selectorgradeです。

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_valuedangling_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_expressionTRUEになる最初の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ファンクションを使用できます。

  • 集計ファンクション(AVGCOUNTなど)

  • 集約ファンクションJSON_ARRAYAGG

  • 集約ファンクションJSON_DATAGUIDE

  • 集約ファンクションJSON_MERGEPATCH

  • 集約ファンクションJSON_OBJECTAGG

  • JSON_TABLE

  • JSON_TRANSFORM

  • JSON条件JSON_TEXTCONTAINS

  • 分析ファンクション(LAGRATIO_TO_REPORTなど)

  • 変換ファンクションBIN_TO_NUM

  • データ・マイニング・ファンクション(CLUSTER_IDFEATURE_VALUEなど)

  • エンコーディング・ファンクションおよびデコーディング・ファンクション(DECODEDUMPなど)

  • モデル・ファンクション(ITERATION_NUMBERPREVIOUSなど)

  • オブジェクト参照ファンクション(REFVALUEなど)

  • 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ファンクションの有効な引数であるCHARVARCHAR2および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静的定数

    静的定数の詳細は、「静的定数」を参照してください。

  • NULL

関連項目:

PLS_INTEGERデータ型の詳細は、「PLS_INTEGERおよびBINARY_INTEGERデータ型」を参照してください

静的なBOOLEAN式

静的なBOOLEAN式には次のものがあります。

  • BOOLEANリテラル(TRUEFALSEまたはNULL)

  • BOOLEAN静的定数

    静的定数の詳細は、「静的定数」を参照してください。

  • xおよびyは、静的なPLS_INTEGER式です。

    • x > y

    • x < y

    • x >= y

    • x <= y

    • x = y

    • x <> y

    静的なPLS_INTEGER式の詳細は、「静的なPLS_INTEGER式」を参照してください。

  • xおよびyBOOLEAN式です。

    • 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式には次のものがあります。

関連項目:

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リファレンス』を参照してください。

関連項目:

例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;
/