プライマリ・コンテンツに移動
Oracle Database PL/SQL言語リファレンス
12c リリース1 (12.1)
B71296-06
目次へ移動
目次
索引へ移動
索引

前
次

2 PL/SQL言語の基礎

PL/SQL言語の基本的なコンポーネントについて説明します。

キャラクタ・セット

PL/SQLで処理したりデータベースに格納する文字データはすべて、一連のバイトで表現する必要があります。単一の文字をバイトで表現したものを文字コードと呼びます。文字コードのセットをキャラクタ・セットと呼びます。

すべてのOracleデータベースでは、データベース・キャラクタ・セットと各国語キャラクタ・セットがサポートされています。また、PL/SQLでも同様に、これらのキャラクタ・セットがサポートされています。このマニュアルでは、データベース・キャラクタ・セットおよび各国語キャラクタ・セットをPL/SQLで使用する方法を説明します。

ここでのトピック

関連項目:

キャラクタ・セットの概要は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

データベース・キャラクタ・セット

PL/SQLでは、データベース・キャラクタ・セットを使用して次のものを表現します。

データベース・キャラクタ・セットは、サポートされている各文字を特定の1バイトにマッピングするシングルバイト、またはサポートされている各文字を一連の1、2、3または4バイトにマッピングする可変幅マルチバイトのいずれかで構成されます。1つの文字コードに含まれる最大バイト数はキャラクタ・セットによって異なります。

すべてのデータベース・キャラクタ・セットには、次の基本文字が含まれます。

  • ラテン文字(AからZおよびaからz)

  • 10進数(0から9)

  • 記号文字(表2-1を参照)

  • 空白文字(空白タブおよび改行およびキャリッジ・リターン)

基本文字のみを使用するPL/SQLソース・テキストは、すべてのデータベースで格納およびコンパイルできます。基本文字以外の文字を使用するPL/SQLソース・テキストは、その文字をサポートするデータベース・キャラクタ・セットが設定されたデータベースのみで格納およびコンパイルできます。

表2-1 すべてのデータベース・キャラクタ・セットに含まれている記号文字

記号 名前

(

左丸カッコ

)

右丸カッコ

<

左山カッコ

>

右山カッコ

+

プラス記号

-

ハイフンまたはマイナス記号

*

アスタリスク

/

スラッシュ

=

等号

,

カンマ

;

セミコロン

:

コロン

.

ピリオド

!

感嘆符

?

疑問符

'

アポストロフィ(一重引用符)

"

引用符(二重引用符)

@

アットマーク

%

パーセント記号

#

シャープ記号

$

ドル記号

_

アンダースコア

|

縦線

関連項目:

データベース・キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

各国語キャラクタ・セット

PL/SQLでは、各国語キャラクタ・セットを使用して、NCHARNVARCHAR2およびNCLOBの各データ型の文字値を表現します。

関連項目:

  • これらのデータ型の詳細は、「SQLデータ型」を参照してください

  • 各国語キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

字句単位

PL/SQLの字句単位(デリミタ、識別子、リテラル、プラグマおよびコメント)は、PL/SQLの最小の個別構成要素です。

ここでのトピック

デリミタ

デリミタは、PL/SQLで特別な意味を持つ文字、または文字の組合せです。

デリミタの中にデリミタ以外の文字(空白文字を含む)を埋め込まないでください。

表2-2に、PL/SQLのデリミタの概要を示します。

表2-2 PL/SQLのデリミタ

デリミタ 意味

+

加算演算子

:=

代入演算子

=>

結合演算子

%

属性のインジケータ

'

文字列のデリミタ

.

構成要素のインジケータ

||

連結演算子

/

除算演算子

**

指数演算子

(

式またはリストのデリミタ(開始)

)

式またはリストのデリミタ(終了)

:

ホスト変数のインジケータ

,

項目のセパレータ

<<

ラベルのデリミタ(開始)

>>

ラベルのデリミタ(終了)

/*

複数行コメントのデリミタ(開始)

*/

複数行コメントのデリミタ(終了)

*

乗算演算子

"

二重引用符で囲んだ識別子のデリミタ

..

範囲演算子

=

関係演算子(等しい)

<>

関係演算子(等しくない)

!=

関係演算子(等しくない)

~=

関係演算子(等しくない)

^=

関係演算子(等しくない)

<

関係演算子(より小さい)

>

関係演算子(より大きい)

<=

関係演算子(以下)

>=

関係演算子(以上)

@

リモート・アクセスのインジケータ

--

単一行コメントのインジケータ

;

文の終了記号

-

減算演算子または否定演算子

識別子

識別子は、次に示すPL/SQL要素に名前を付けます。

  • 定数

  • カーソル

  • 例外

  • キーワード

  • ラベル

  • パッケージ

  • 予約語

  • サブプログラム

  • 変数

英字かどうかに関係なく、識別子に含まれているすべての文字が意味を持ちます。たとえば、識別子lastnamelast_nameは別のものとみなされます。

隣接する識別子は、1つ以上の空白またはデリミタ文字で区切る必要があります。

「ユーザー定義の引用識別子」で説明している例を除き、PL/SQLでは識別子の大/小文字が区別されません。たとえば、識別子lastnameLastNameおよびLASTNAMEは同じものとみなされます。

ここでのトピック

予約語およびキーワード

予約語キーワードは、PL/SQLで特別な意味を持つ識別子です。

通常のユーザー定義の識別子として、予約語を使用することはできません。予約語は、ユーザー定義の引用識別子として使用できますが、使用しないことをお薦めします。詳細は、「ユーザー定義の引用識別子」を参照してください。

キーワードは、通常のユーザー定義の識別子として使用できますが、使用しないことをお薦めします。

PL/SQLの予約語のリストは表D-1、キーワードのリストは表D-2を参照してください。

事前定義の識別子

事前定義の識別子は、事前定義のパッケージSTANDARDで宣言されています。

事前定義の識別子の例としては、例外INVALID_NUMBERがあります。

事前定義の識別子のリストを取得するには、DBAロールを持つユーザーとしてOracle Databaseに接続し、次の問合せを使用します。

SELECT TYPE_NAME FROM ALL_TYPES WHERE PREDEFINED='YES';

事前定義の識別子は、ユーザー定義の識別子として使用できますが、使用しないことをお薦めします。ローカルの宣言はグローバルな宣言をオーバーライドします(「識別子の有効範囲と可視性」を参照)。

ユーザー定義の識別子

ユーザー定義の識別子の特性は次のとおりです。

  • データベース・キャラクタ・セットの文字で構成されます。

  • 通常の識別子と引用識別子があります。

ヒント:

ユーザー定義の識別子は、意味のあるものにします。たとえば、cost_per_thousandは意味が明白ですが、cptは意味があいまいです。

通常のユーザー定義の識別子

通常のユーザー定義の識別子の特性は次のとおりです。

  • 先頭は英字です。

  • 文字、数字および次の記号を使用できます。

    • ドル記号($)

    • シャープ記号(#)

    • アンダースコア(_)

  • 予約語(表D-1を参照)は使用できません。

データベース・キャラクタ・セットには、文字および数字として分類される文字が定義されています。データベース・キャラクタ・セットでの識別子表現は、30バイトを超えないように定義する必要があります。

通常のユーザー定義の識別子として有効な例を次に示します。

X
t2
phone#
credit_limit
LastName
oracle$number
money$$$tree
SN##
try_again_

通常のユーザー定義の識別子として無効な例を次に示します。

mine&yours
debit-amount
on/off
user id
ユーザー定義の引用識別子

ユーザー定義の引用識別子は、二重引用符で囲まれています。二重引用符の間には、二重引用符、改行文字およびNULL文字以外の任意の文字をデータベース・キャラクタ・セットから使用できます。たとえば、次の識別子を使用できます。

"X+Y"
"last name"
"on/off switch"
"employee(s)"
"*** header info ***"

データベース・キャラクタ・セットでの引用識別子表現は、(二重引用符を除いて)30バイトを超えないように定義する必要があります。

ユーザー定義の引用識別子では大/小文字が区別されますが、例外が1つあります。ユーザー定義の引用識別子から二重引用符を除いたものが有効な通常のユーザー定義の識別子である場合は、その識別子を参照するときの二重引用符は省略可能になり、省略した場合は識別子の大/小文字が区別されなくなります。

例2-1のユーザー定義の引用識別子"HELLO"は、二重引用符がなくても有効な通常のユーザー定義の識別子です。したがって、Helloという参照は有効です。

例2-2"Hello"という参照は無効です。これは、二重引用符を付けると識別子の大/小文字が区別されるためです。お薦めしませんが、予約語をユーザー定義の引用識別子として使用することができます。予約語は有効な通常のユーザー定義の識別子ではないため、識別子は二重引用符で囲む必要があり、大/小文字は常に区別されます。

例2-3では、ユーザー定義の引用識別子"BEGIN""Begin"および"begin"が宣言されています。BEGINBeginおよびbeginは同じ予約語を表しますが、"BEGIN""Begin"および"begin"は異なる識別子を表します。

例2-4では、二重引用符で囲まずに、予約語であるユーザー定義の引用識別子を参照しています。

例2-5では、大/小文字の区別を無視して、予約語であるユーザー定義の引用識別子を参照しています。

例2-1 ユーザー定義の引用識別子に対する、大/小文字を区別しない有効な参照

DECLARE
  "HELLO" varchar2(10) := 'hello';
BEGIN
  DBMS_Output.Put_Line(Hello);
END;
/

結果:

hello

例2-2 ユーザー定義の引用識別子に対する、大/小文字を区別しない無効な参照

DECLARE
  "HELLO" varchar2(10) := 'hello';
BEGIN
  DBMS_Output.Put_Line("Hello");
END;
/

結果:

  DBMS_Output.Put_Line("Hello");
                        *
ERROR at line 4:
ORA-06550: line 4, column 25:
PLS-00201: identifier 'Hello' must be declared
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

例2-3 ユーザー定義の引用識別子としての予約語

DECLARE
  "BEGIN" varchar2(15) := 'UPPERCASE';
  "Begin" varchar2(15) := 'Initial Capital';
  "begin" varchar2(15) := 'lowercase';
BEGIN
  DBMS_Output.Put_Line("BEGIN");
  DBMS_Output.Put_Line("Begin");
  DBMS_Output.Put_Line("begin");
END;
/

結果:

UPPERCASE
Initial Capital
lowercase
 
PL/SQL procedure successfully completed.

例2-4 二重引用符の省略

DECLARE
  "HELLO" varchar2(10) := 'hello';  -- HELLO is not a reserved word
  "BEGIN" varchar2(10) := 'begin';  -- BEGIN is a reserved word
BEGIN
  DBMS_Output.Put_Line(Hello);      -- Double quotation marks are optional
  DBMS_Output.Put_Line(BEGIN);      -- Double quotation marks are required
end;
/

結果:

  DBMS_Output.Put_Line(BEGIN);      -- Double quotation marks are required
                       *
ERROR at line 6:
ORA-06550: line 6, column 24:
PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following:
( ) - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
table continue avg count current exists max min prior sql
stddev sum variance execute multiset the both leading
trailing forall merge year month day hour minute second
timezone_hour timezone_minute timezone_region timezone_abbr
time timestamp interval date
<a string literal with character set specificat

例2-5 大/小文字の区別の無視

DECLARE
  "HELLO" varchar2(10) := 'hello';  -- HELLO is not a reserved word
  "BEGIN" varchar2(10) := 'begin';  -- BEGIN is a reserved word
BEGIN
  DBMS_Output.Put_Line(Hello);      -- Identifier is case-insensitive
  DBMS_Output.Put_Line("Begin");    -- Identifier is case-sensitive
END;
/

結果:

  DBMS_Output.Put_Line("Begin");    -- Identifier is case-sensitive
                        *
ERROR at line 6:
ORA-06550: line 6, column 25:
PLS-00201: identifier 'Begin' must be declared
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored

リテラル

リテラルは、識別子で表現したり他の値から計算する必要がない値です。

たとえば、123は整数リテラルで'abc'は文字リテラルですが、1+2はリテラルではありません。

PL/SQLリテラルにはすべてのSQLリテラル(『Oracle Database SQL言語リファレンス』を参照)およびBOOLEANリテラル(SQLにはありません)が含まれます。BOOLEANリテラルとは、事前定義の論理値TRUEFALSEまたはNULLのことです。NULLは、不明な値を表します。

注意:

『Oracle Database SQL言語リファレンス』と同様に、このマニュアルでも文字リテラルおよび文字列という用語を同じ意味で使用しています。

PL/SQLで文字リテラルを使用する場合は、次のことに注意してください。

  • 文字リテラルは大/小文字が区別されます。

    たとえば、'Z''z'は別のものとみなされます。

  • 空白文字が意味を持ちます。

    たとえば、次のリテラルは別のものとみなされます。

    'abc'
    ' abc'
    'abc '
    ' abc '
    'a b c'
    
  • PL/SQLには、「文字列が次のソース行へ続く」ことを意味する行継続文字がありません。文字列を次のソース行へ続けた場合、文字列に改行文字が含まれます。

    たとえば、次のPL/SQLコードの場合:

    BEGIN
      DBMS_OUTPUT.PUT_LINE('This string breaks
    here.');
    END;
    /
    

    次のように印刷されます。

    This string breaks
    here.
    

    文字列が1つのソース行に収まらない場合に改行文字を含まないようにするには、連結演算子(||)を使用して文字列を構築します。

    たとえば、次のPL/SQLコードの場合:

    BEGIN
      DBMS_OUTPUT.PUT_LINE('This string ' ||
                           'contains no line-break character.');
    END;
    /
    

    次のように印刷されます。

    This string contains no line-break character.
    

    連結演算子の詳細は、「連結演算子」を参照してください。

  • '0'から'9'は、整数リテラルの0から9と同じではありません。

    ただし、PL/SQLによって整数に変換されるため、算術式内で使用できます。

  • 0(ゼロ)文字の文字リテラルは値NULLを持っており、NULL文字列と呼ばれます。

    ただし、このNULL値はBOOLEAN値のNULLではありません。

  • 通常の文字リテラルは、データベース・キャラクタ・セット内の文字で構成されます。

    データベース・キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

  • 各国語文字リテラルは、各国語キャラクタ・セット内の文字で構成されます。

    各国語キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

プラグマ

プラグマは、コンパイラに対する命令で、コンパイル時に処理されます。プラグマの詳細は、次の項を参照してください。

コメント

PL/SQLコンパイラは、コメントを無視します。コメントを付けておくと、他のアプリケーション開発者がソース・テキストを理解しやすくなります。

一般に、コメントは各コード・セグメントの目的や使用方法を説明するために使用します。また、廃止されたコード部分や作成途中のコード部分をコメントに入れて無効化することもできます。

ここでのトピック

単一行コメント

単一行コメントは--で始まり、その行の終わりまで続きます。

注意:

Oracleプリコンパイラ・プログラムが動的に処理するPL/SQLブロックの中に単一行コメントを置かないでください。Oracleプリコンパイラ・プログラムでは行の終わりを示す文字が無視されるため、単一行コメントはブロックの末尾で終了します。

例2-6には、3つの単一行コメントがあります。

プログラムのテストまたはデバッグ中に、コード内の1行をコメントにすることによって無効にできます。次に例を示します。

-- DELETE FROM employees WHERE comm_pct IS NULL

例2-6 単一行コメント

DECLARE
  howmany     NUMBER;
  num_tables  NUMBER;
BEGIN
  -- Begin processing
  SELECT COUNT(*) INTO howmany
  FROM USER_OBJECTS
  WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables
  num_tables := howmany;       -- Compute another value
END;
/

複数行コメント

複数行コメントは、/*で始まって*/で終わり、複数行にまたがることができます。

例2-7には、2つの複数行コメントがあります。(SQLファンクションTO_CHARは、引数に相当する文字を戻します。TO_CHARの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)

複数行コメントのデリミタを使用すると、コードの一部分をコメントにできます。その場合、複数行コメントをネストしないように注意してください。複数行コメントに別の複数行コメントを含めることはできません。ただし、複数行コメントに単一行コメントを含めることはできます。たとえば、次の場合、構文エラーが発生します。

/*
  IF 2 + 2 = 4 THEN
    some_condition := TRUE;
  /* We expect this THEN to always be performed */
  END IF;
*/

次の場合、構文エラーは発生しません。

/*
  IF 2 + 2 = 4 THEN
    some_condition := TRUE;
  -- We expect this THEN to always be performed
  END IF;
*/

例2-7 複数行コメント

DECLARE
  some_condition  BOOLEAN;
  pi              NUMBER := 3.1415926;
  radius          NUMBER := 15;
  area            NUMBER;
BEGIN
  /* Perform some simple tests and assignments */
 
  IF 2 + 2 = 4 THEN
    some_condition := TRUE;
  /* We expect this THEN to always be performed */
  END IF;
 
  /* This line computes the area of a circle using pi,
  which is the ratio between the circumference and diameter.
  After the area is computed, the result is displayed. */
 
  area := pi * radius**2;
  DBMS_OUTPUT.PUT_LINE('The area is: ' || TO_CHAR(area));
END;
/
 

結果:

The area is: 706.858335

字句単位の間の空白文字

字句単位の間に空白文字を挿入できます。多くの場合、これによってソース・テキストが読みやすくなります。

例2-8 空白文字によるソース・テキストの読みやすさの向上

DECLARE
  x    NUMBER := 10;
  y    NUMBER := 5;
  max  NUMBER;
BEGIN
  IF x>y THEN max:=x;ELSE max:=y;END IF;  -- correct but hard to read
  
  -- Easier to read:
  
  IF x > y THEN
    max:=x;
  ELSE
    max:=y;
  END IF;
END;
/

宣言

宣言によって、指定されたデータ型の値の記憶域を割り当て、値を参照できるように格納場所に名前を付けます。

オブジェクトは、参照する前に宣言しておく必要があります。宣言は、任意のブロック、サブプログラムまたはパッケージの宣言部で使用できます。

ここでのトピック

変数と定数以外のオブジェクトの宣言の詳細は、「ブロック」declare_sectionの構文を参照してください。

NOT NULL制約

スカラー変数または定数(またはコンポジット変数または定数のスカラー・コンポーネント)には、NOT NULL制約を指定できます。

NOT NULL制約を指定すると、その項目にNULL値を代入できなくなります。この制約は、(データ型から)暗黙的に指定するか、または明示的に指定することができます。

NOT NULLを指定するスカラー変数の宣言では、暗黙的か明示的かに関係なく、初期値を変数に代入する必要があります(スカラー変数のデフォルトの初期値はNULLであるため)。

PL/SQLは長さが0(ゼロ)の文字値をすべてNULL値とみなします。これには文字関数やブール式によって戻された値が含まれます。

NULL値かどうかをテストするには、「IS [NOT] NULL演算子」を使用します。

例2-9 NOT NULL制約が指定された変数の宣言

この例では、変数acct_idNOT NULL制約を明示的に指定し、変数abおよびcにはデータ型から暗黙的に指定します。

DECLARE
  acct_id INTEGER(4) NOT NULL := 9999;
  a NATURALN                  := 9999;
  b POSITIVEN                 := 9999;
  c SIMPLE_INTEGER            := 9999;
BEGIN
  NULL;
END;
/

例2-10 NULL値に初期化される変数

この例では、すべての変数がNULLに初期化されます。

DECLARE
  null_string  VARCHAR2(80) := TO_CHAR('');
  address      VARCHAR2(80);
  zip_code     VARCHAR2(80) := SUBSTR(address, 25, 0);
  name         VARCHAR2(80);
  valid        BOOLEAN      := (name != '');
BEGIN
  NULL;
END;
/

変数の宣言

変数の宣言では、変数の名前とデータ型を常に指定します。

ほとんどのデータ型の場合、変数を宣言するときに初期値を指定することもできます。

変数名は有効なユーザー定義の識別子である必要があります。

データ型は、任意のPL/SQLデータ型を選択できます。PL/SQLデータ型にはSQLデータ型が含まれます。データ型は、スカラー(内部コンポーネントなし)またはコンポジット(内部コンポーネントあり)のいずれかです。

例2-11 スカラー変数の宣言

この例では、複数のスカラー・データ型の変数を宣言します。

DECLARE
  part_number       NUMBER(6);     -- SQL data type
  part_name         VARCHAR2(20);  -- SQL data type
  in_stock          BOOLEAN;       -- PL/SQL-only data type
  part_price        NUMBER(6,2);   -- SQL data type
  part_description  VARCHAR2(50);  -- SQL data type
BEGIN
  NULL;
END;
/

関連トピック

定数の宣言

定数は、変更されない値を保持します。

「変数の宣言」の内容は定数の宣言にも当てはまりますが、定数の宣言には必要なものがさらに2つ(キーワードCONSTANTと定数の初期値)あります。(定数の初期値は永続的な値になります。)

例2-12 定数の宣言

この例では、スカラー・データ型の3つの定数を宣言します。

DECLARE
  credit_limit     CONSTANT REAL    := 5000.00;  -- SQL data type
  max_days_in_year CONSTANT INTEGER := 366;      -- SQL data type
  urban_legend     CONSTANT BOOLEAN := FALSE;    -- PL/SQL-only data type
BEGIN
  NULL;
END;
/

関連項目

変数および定数の初期値

変数宣言では、NOT NULL制約を指定しないかぎり、初期値はオプションです。定数の宣言では、初期値は必須です。

ブロックまたはサブプログラムに宣言が含まれている場合は、ブロックまたはサブプログラムに制御が渡されるたびに、変数または定数に初期値が代入されます。宣言がパッケージ仕様部にある場合は、(変数または定数がパブリックかプライベートかには関係なく)セッションごとに初期値が変数または定数に代入されます。

初期値を指定するには、代入演算子(:=)またはキーワードDEFAULTを使用し、その後に式を指定します。式には、事前に宣言済の定数と、事前に初期化済の変数を使用できます。

変数に初期値を指定しない場合は、他のコンテキストで使用する前に、値を代入します。

例2-13 初期値が指定された変数および定数の宣言

この例では、宣言する定数および変数に初期値を代入します。areaの初期値は、事前に宣言済の定数piおよび事前に初期化済の変数radiusに応じて異なります。

DECLARE
  hours_worked    INTEGER := 40;
  employee_count  INTEGER := 0;

  pi     CONSTANT REAL := 3.14159;
  radius          REAL := 1;
  area            REAL := (pi * radius**2);
BEGIN
  NULL;
END;
/

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

この例では、変数counterの初期値はデフォルトのNULLです。この例では、「IS [NOT] NULL演算子」を使用して、NULLが0(ゼロ)とは異なることを示しています。

DECLARE
  counter INTEGER;  -- initial value is NULL by default
BEGIN
  counter := counter + 1;  -- NULL + 1 is still NULL
  
  IF counter IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('counter is NULL.');
  END IF;
END;
/
 

結果:

counter is NULL.

関連トピック

%TYPE属性を使用した項目の宣言

%TYPE属性を使用すると、事前に宣言されている変数または列と同じデータ型のデータ項目を(データ型を知らなくても)宣言できます。参照先項目の宣言が変更されると、それに応じて参照元項目の宣言も変更されます。

次に宣言の構文を示します。

referencing_item referenced_item%TYPE;

参照元項目および参照先項目にすることができる項目の種類は、「%TYPE属性」を参照してください。

参照元項目は、参照先項目から次のものを継承します。

  • データ型およびサイズ

  • 制約(参照先項目が列である場合を除く)

参照元項目は、参照先項目の初期値は継承しません。そのため、参照元項目でNOT NULL制約が指定または継承される場合は、参照元項目の初期値を指定する必要があります。

%TYPE属性は、データベースの値を保持する変数を宣言する場合に特に便利です。列と同じ型の変数を宣言する構文は、次のようになります。

variable_name table_name.column_name%TYPE;

関連項目:

「%ROWTYPE属性を使用した項目の宣言」(この属性を使用すると、データベースの表またはビュー内の行の全体または一部を表すレコード変数を宣言できます)

例2-15 列と同じ型の変数の宣言

この例では、変数surnameは、NOT NULL制約が指定されている列employees.last_nameのデータ型とサイズを継承しています。surnameNOT NULL制約を継承しないため、その宣言に初期値は不要です。

DECLARE
  surname  employees.last_name%TYPE;
BEGIN
  DBMS_OUTPUT.PUT_LINE('surname=' || surname);
END;
/

結果:

surname=

例2-16 別の変数と同じ型の変数の宣言

この例では、変数surnameは変数nameのデータ型、サイズおよびNOT NULL制約を継承しています。surnamenameの初期値を継承しないため、その宣言には初期値(25文字以内)が必要です。

DECLARE
  name     VARCHAR(25) NOT NULL := 'Smith';
  surname  name%TYPE := 'Jones';
BEGIN
  DBMS_OUTPUT.PUT_LINE('name=' || name);
  DBMS_OUTPUT.PUT_LINE('surname=' || surname);
END;
/

結果:

name=Smith
surname=Jones

識別子に対する参照

識別子を参照するとき、名前には、単純名、修飾名、リモート名または修飾リモート名を使用します。

識別子の単純名は、その宣言に含まれる名前です。次に例を示します。

DECLARE
  a INTEGER;  -- Declaration
BEGIN
  a := 1;     -- Reference with simple name
END;
/

識別子が名前付きPL/SQLユニットで宣言されている場合、その参照に修飾名を使用できます(場合によっては必須)。構文(ドット表記法と呼ばれる)は次のとおりです。

unit_name.simple_identifier_name

たとえば、パッケージpで識別子aを宣言している場合、その識別子は修飾名p.aで参照できます。ユニット名も修飾できます(場合によっては必須)。識別子を参照できない場合は、その識別子を修飾する必要があります(「識別子の有効範囲と可視性」を参照)。

リモート・データベース上のオブジェクトに識別子で名前が付けられている場合、その識別子はリモート名で参照する必要があります。次に構文を示します。

simple_identifier_name@link_to_remote_database

リモート・データベース上にあるPL/SQLユニットで識別子が宣言されている場合、その識別子は修飾リモート名で参照する必要があります。次に構文を示します。

unit_name.simple_identifier_name@link_to_remote_database

リモート・スキーマ・オブジェクトのシノニムは作成できますが、PL/SQLのサブプログラムまたはパッケージ内で宣言されたオブジェクトのシノニムは作成できません。シノニムを作成するには、SQL文CREATE SYNONYMを使用します(『Oracle Database SQL言語リファレンス』を参照)。

PL/SQLでのあいまいな名前の解決方法の詳細は、「PL/SQLの名前解決」を参照してください。

注意:

パッケージSTANDARDおよびDBMS_STANDARDで宣言された識別子は、同じ名前のローカル識別子を宣言していないかぎり、パッケージ名で修飾しなくても参照できます(「識別子の有効範囲と可視性」を参照)。

識別子の有効範囲と可視性

識別子の有効範囲とは、その識別子の参照が可能な、PL/SQLユニットの領域です。識別子の可視性とは、修飾なしでその識別子の参照が可能な、PL/SQLユニットの領域です。識別子は、自身が宣言されているPL/SQLユニットに対してローカルです。そのユニットにサブユニットがある場合、識別子はサブユニットに対してグローバルです。

サブユニットでグローバル識別子が再宣言されると、そのサブユニット内では両方の識別子が有効範囲内にあることになりますが、ローカル識別子のみが表示されます。サブユニットでグローバル識別子を参照するには、グローバル識別子が宣言されているユニットの名前でグローバル識別子を修飾する必要があります。そのユニットに名前がない場合、サブユニットでグローバル識別子を参照することはできません。

PL/SQLユニットは、あるユニットから同じレベルの他のユニットで宣言されている識別子への参照はできません。そのような識別子は、そのブロックに対してローカルでもグローバルでもないためです。

同じPL/SQLユニット内で、同じ識別子を2回宣言することはできません。これを行うと、重複する識別子を参照したときにエラーが発生します。

2つの異なるユニットであれば、同じ識別子を宣言できます。その識別子で表される2つのオブジェクトは区別されます。片方を変更しても、もう片方に影響は及びません。

同じ有効範囲内では、混乱や予期しない結果を回避するためにラベルとサブプログラムに一意の名前を付けます。

例2-17 識別子の有効範囲と可視性

この例に、いくつかの識別子の有効範囲と可視性を示します。最初のサブブロックで、グローバル識別子aが再宣言されています。グローバル変数aを参照するには、最初のサブブロックで、外側のブロックの名前を使用して変数を修飾する必要がありますが、外側のブロックには名前がありません。そのため、最初のサブブロックではグローバル変数aを参照することはできず、参照できるのはローカル変数aのみです。サブブロックは同じレベルにあるため、最初のサブブロックはdを参照できず、2番目のサブブロックはcを参照できません。

-- Outer block:
DECLARE
  a CHAR;  -- Scope of a (CHAR) begins
  b REAL;    -- Scope of b begins
BEGIN
  -- Visible: a (CHAR), b
  
  -- First sub-block:
  DECLARE
    a INTEGER;  -- Scope of a (INTEGER) begins
    c REAL;       -- Scope of c begins
  BEGIN
    -- Visible: a (INTEGER), b, c
    NULL;
  END;          -- Scopes of a (INTEGER) and c end

  -- Second sub-block:
  DECLARE
    d REAL;     -- Scope of d begins
  BEGIN
    -- Visible: a (CHAR), b, d
    NULL;
  END;          -- Scope of d ends

-- Visible: a (CHAR), b
END;            -- Scopes of a (CHAR) and b end
/

例2-18 ブロック・ラベルによる、再宣言されたグローバル識別子の修飾

この例では、外側のブロックにouterという名前のラベルを付けています。そのため、サブブロックでは、グローバル変数birthdateを再宣言した後、ブロックのラベルを使用して変数名を修飾することで、このグローバル変数を参照できます。サブブロックでは、単純名によってローカル変数birthdateも参照できます。

<<outer>>  -- label
DECLARE
  birthdate DATE := TO_DATE('09-AUG-70', 'DD-MON-YY');
BEGIN
  DECLARE
    birthdate DATE := TO_DATE('29-SEP-70', 'DD-MON-YY');
  BEGIN
    IF birthdate = outer.birthdate THEN
      DBMS_OUTPUT.PUT_LINE ('Same Birthday');
    ELSE
      DBMS_OUTPUT.PUT_LINE ('Different Birthday');
    END IF;
  END;
END;
/
 

結果:

Different Birthday

例2-19 サブプログラム名による識別子の修飾

この例では、プロシージャcheck_creditで、変数ratingとファンクションcheck_ratingを宣言しています。ファンクションで変数を再宣言します。その後、ファンクションはグローバル変数をプロシージャ名で修飾して参照します。

CREATE OR REPLACE PROCEDURE check_credit (credit_limit NUMBER) AS
  rating NUMBER := 3;
  
  FUNCTION check_rating RETURN BOOLEAN IS
    rating  NUMBER := 1;
    over_limit  BOOLEAN;
  BEGIN
    IF check_credit.rating <= credit_limit THEN  -- reference global variable
      over_limit := FALSE;
    ELSE
      over_limit := TRUE;
      rating := credit_limit;                    -- reference local variable
    END IF;
    RETURN over_limit;
  END check_rating;
BEGIN
  IF check_rating THEN
    DBMS_OUTPUT.PUT_LINE
      ('Credit rating over limit (' || TO_CHAR(credit_limit) || ').  '
      || 'Rating: ' || TO_CHAR(rating));
  ELSE
    DBMS_OUTPUT.PUT_LINE
      ('Credit rating OK.  ' || 'Rating: ' || TO_CHAR(rating));
  END IF;
END;
/
 
BEGIN
  check_credit(1);
END;
/
 

結果:

Credit rating over limit (1).  Rating: 3

例2-20 同じ有効範囲での重複する識別子

同じPL/SQLユニット内で、同じ識別子を2回宣言することはできません。この例に示すとおり、これを行うと、重複する識別子を参照したときにエラーが発生します。

DECLARE
  id  BOOLEAN;
  id  VARCHAR2(5);  -- duplicate identifier
BEGIN
  id := FALSE;
END;
/
 

結果:

  id := FALSE;
  *
ERROR at line 5:
ORA-06550: line 5, column 3:
PLS-00371: at most one declaration for 'ID' is permitted
ORA-06550: line 5, column 3:
PL/SQL: Statement ignored

例2-21 異なるユニットでの同じ識別子の宣言

2つの異なるユニットであれば、同じ識別子を宣言できます。その識別子で表される2つのオブジェクトは区別されます。この例に示すとおり、1つを変更しても、もう1つに影響はありません。同じ有効範囲内では、混乱や予期しない結果を回避するためにラベルとサブプログラムに一意の名前を付けます。

DECLARE
  PROCEDURE p
  IS
    x VARCHAR2(1);
  BEGIN
    x := 'a';  -- Assign the value 'a' to x
    DBMS_OUTPUT.PUT_LINE('In procedure p, x = ' || x);
  END;
 
  PROCEDURE q
  IS
    x VARCHAR2(1);
  BEGIN
    x := 'b';  -- Assign the value 'b' to x
    DBMS_OUTPUT.PUT_LINE('In procedure q, x = ' || x);
  END;
 
BEGIN
  p;
  q;
END;
/

結果:

In procedure p, x = a
In procedure q, x = b

例2-22 同じ有効範囲内で同じ名前を持つラベルとサブプログラム

この例では、echoがブロックとサブプログラムの両方の名前になっています。ブロックおよびサブプログラムの両方で、xという変数を宣言しています。サブプログラム内では、echo.xは、グローバル変数xではなく、ローカル変数xを参照します。

<<echo>>
DECLARE
  x  NUMBER := 5;
  
  PROCEDURE echo AS
    x  NUMBER := 0;
  BEGIN
    DBMS_OUTPUT.PUT_LINE('x = ' || x);
    DBMS_OUTPUT.PUT_LINE('echo.x = ' || echo.x);
  END;
 
BEGIN
  echo;
END;
/
 

結果:

x = 0
echo.x = 0

例2-23 複数の重複したラベルを使用するブロック

この例では、外側のブロックに対して2つのラベルcompute_ratioanother_labelが存在します。2番目のラベルは、内側のブロックに再度現れます。内側のブロック内では、another_label.denominatorはローカル変数denominatorを参照し、グローバル変数denominatorを参照しないため、ZERO_DIVIDEエラーが発生します。

<<compute_ratio>>
<<another_label>>
DECLARE
  numerator   NUMBER := 22;
  denominator NUMBER := 7;
BEGIN
  <<another_label>>
  DECLARE
    denominator NUMBER := 0;
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Ratio with compute_ratio.denominator = ');
    DBMS_OUTPUT.PUT_LINE(numerator/compute_ratio.denominator);
 
    DBMS_OUTPUT.PUT_LINE('Ratio with another_label.denominator = ');
    DBMS_OUTPUT.PUT_LINE(numerator/another_label.denominator);
 
  EXCEPTION
    WHEN ZERO_DIVIDE THEN
      DBMS_OUTPUT.PUT_LINE('Divide-by-zero error: can''t divide '
        || numerator || ' by ' || denominator);
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Unexpected error.');
  END another_label;
END compute_ratio;
/
 

結果:

Ratio with compute_ratio.denominator =
3.14285714285714285714285714285714285714
Ratio with another_label.denominator =
Divide-by-zero error: cannot divide 22 by 0

変数への値の代入

変数を宣言した後、次の方法でその変数に値を代入できます。

  • 代入文を使用して式の値を代入する方法。

  • SELECT INTO文またはFETCH文を使用して表の値を代入する方法。

  • OUTパラメータまたはIN OUTパラメータとしてサブプログラムに渡し、サブプログラム内で値を代入する方法。

変数と値のデータ型には、互換性が必要です。あるデータ型を暗黙的に別のデータ型に変換できる場合、この2つのデータ型には互換性があります。暗黙的なデータ変換の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

ここでのトピック

代入文を使用した変数への値の代入

式の値を変数に代入するには、次の形式の代入文を使用します。

variable_name := expression;

代入文の構文の詳細は、「代入文」を参照してください。

式の構文は、「式」を参照してください。

例2-24 代入文を使用した変数への値の代入

この例では、複数の変数を宣言(一部には初期値も指定)してから、代入文を使用して式の値を変数に代入します。

DECLARE  -- You can assign initial values here
  wages          NUMBER;
  hours_worked   NUMBER := 40;
  hourly_salary  NUMBER := 22.50;
  bonus          NUMBER := 150;
  country        VARCHAR2(128);
  counter        NUMBER := 0;
  done           BOOLEAN;
  valid_id       BOOLEAN;
  emp_rec1       employees%ROWTYPE;
  emp_rec2       employees%ROWTYPE;
  TYPE commissions IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  comm_tab       commissions;
 
BEGIN  -- You can assign values here too
  wages := (hours_worked * hourly_salary) + bonus;
  country := 'France';
  country := UPPER('Canada');
  done := (counter > 100);
  valid_id := TRUE;
  emp_rec1.first_name := 'Antonio';
  emp_rec1.last_name := 'Ortiz';
  emp_rec1 := emp_rec2;
  comm_tab(5) := 20000 * 0.15;
END;
/

SELECT INTO文を使用した変数への値の代入

SELECT INTO文の単純な形式は次のとおりです。

SELECT select_item [, select_item ]... 
INTO variable_name [, variable_name ]...
FROM table_name;

それぞれのselect_itemに、対応する型互換性のあるvariable_nameが必要です。SQLにはBOOLEAN型がないため、variable_nameBOOLEAN変数にはできません。

SELECT INTO文の構文の詳細は、「SELECT INTO文」を参照してください。

例2-25 SELECT INTO文を使用した変数への値の代入

この例では、SELECT INTO文を使用して、employee_idが100である従業員の給与の10%にあたる値を変数bonusに代入します。

DECLARE
  bonus   NUMBER(8,2);
BEGIN
  SELECT salary * 0.10 INTO bonus
  FROM employees
  WHERE employee_id = 100;
END;

DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus));
/

結果:

bonus = 2400

サブプログラムのパラメータとしての変数への値の代入

変数をOUTパラメータまたはIN OUTパラメータとしてサブプログラムに渡し、サブプログラムによってこれらのパラメータに値が代入される場合は、サブプログラムの実行後、その値が変数で保持されます。詳細は、「サブプログラム・パラメータ」を参照してください。

例2-26 IN OUTサブプログラム・パラメータとしての変数への値の代入

この例では、変数new_salをプロシージャadjust_salaryに渡します。このプロシージャによって、対応する仮パラメータsalに値が代入されます。salIN OUTパラメータであるため、プロシージャの実行終了後、代入された値が変数new_salで保持されます。

DECLARE
  emp_salary  NUMBER(8,2);
 
  PROCEDURE adjust_salary (
    emp        NUMBER, 
    sal IN OUT NUMBER,
    adjustment NUMBER
  ) IS
  BEGIN
    sal := sal + adjustment;
  END;
 
BEGIN
  SELECT salary INTO emp_salary
  FROM employees
  WHERE employee_id = 100;
 
  DBMS_OUTPUT.PUT_LINE
   ('Before invoking procedure, emp_salary: ' || emp_salary);
 
  adjust_salary (100, emp_salary, 1000);
 
  DBMS_OUTPUT.PUT_LINE
   ('After invoking procedure, emp_salary: ' || emp_salary);
END;
/
 

結果:

Before invoking procedure, emp_salary: 24000
After invoking procedure, emp_salary: 25000

ブール変数への値の代入

BOOLEAN変数に代入できる値は、TRUEFALSEおよびNULLのみです。

BOOLEANデータ型の詳細は、「ブール・データ型」を参照してください。

例2-27 BOOLEAN変数への値の代入

この例では、BOOLEAN変数doneをデフォルトでNULLに初期化し、リテラル値FALSEを代入して、リテラル値TRUEと比較し、BOOLEAN式の値を代入します。

DECLARE
  done    BOOLEAN;              -- Initial value is NULL by default
  counter NUMBER := 0;
BEGIN
  done := FALSE;                -- Assign literal value
  WHILE done != TRUE            -- Compare to literal value
    LOOP
      counter := counter + 1;
      done := (counter > 500);  -- Assign value of BOOLEAN expression
    END LOOP;
END;
/

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

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

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

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

  3. バイナリ演算子とその2つのオペランド(a+bなど)

オペランドは、変数、定数、リテラル、演算子、ファンクション起動、プレースホルダ、またはその他の式にすることができます。そのため、式は複雑になる場合があります。式の構文の詳細は、「式」を参照してください。

オペランドのデータ型によって、式のデータ型が決まります。式が評価されるたびに、結果としてそのデータ型の値が1つ得られます。結果のデータ型は、式のデータ型です。

連結演算子

連結演算子(||)は、ある文字列オペランドを別の文字列オペランドに追加します。

連結演算子は、例2-29に示すとおり、NULLオペランドを無視します。

連結演算子の構文の詳細は、「character_expression ::=」を参照してください。

例2-28 連結演算子

DECLARE
  x VARCHAR2(4) := 'suit';
  y VARCHAR2(4) := 'case';
BEGIN
  DBMS_OUTPUT.PUT_LINE (x || y);
END;
/
 

結果:

suitcase

例2-29 連結演算子とNULLオペランド

BEGIN
  DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce');
END;
/
 

結果:

applesauce

演算子の優先順位

演算は、単項演算子とオペランド1つか、またはバイナリ演算子とオペランド2つのいずれかです。式内の演算は、演算子の優先順位に応じて評価されます。

表2-3に、優先順位の高い順に演算子を示します。同じ優先順位の演算子は、特に順序を考慮せずに評価されます。

表2-3 演算子の優先順位

演算子 演算

**

指数

+, -

恒等、否定

*, /

乗算、除算

+, -, ||

加算、減算、連結

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

比較

NOT

否定

AND

論理積

OR

論理和

評価の順序を制御するには、例2-30に示すとおり、演算をカッコで囲みます。

カッコがネストされている場合は、最も深くネストされた演算が最初に評価されます。

例2-31では、演算(1+2)および(3+4)が最初に評価され、それぞれ3および7という値が算出されます。次に、演算3*7が評価され、21という結果が算出されます。最後に21/7が評価され、最終的な値として3が算出されます。

カッコが評価の順序に影響しない場合でも、例2-32のように、カッコを使用してわかりやすくすることができます。

例2-33では、より複雑ないくつかの式での演算子の優先順位とカッコの効果を示します。

例2-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

例2-31 ネストしたカッコを使用した式

DECLARE
  a INTEGER := ((1+2)*(3+4))/7;
BEGIN
  DBMS_OUTPUT.PUT_LINE('a = ' || TO_CHAR(a));
END;
/

結果:

a = 3

例2-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

例2-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は単項演算子です。

表2-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

例2-34では、BOOLEAN変数の値を出力するprint_booleanというプロシージャを作成します。このプロシージャでは、「IS [NOT] NULL演算子」が使用されます。この章で紹介するいくつかの例で、print_booleanを起動しています。

表2-4および例2-35に示すとおり、両方のオペランドがTRUEである場合にのみ、ANDTRUEを戻します。

表2-4および例2-36に示すとおり、一方のオペランドがTRUEである場合、ORTRUEを戻します。(例2-36では、例2-35print_booleanプロシージャを起動します。)

表2-4および例2-37に示すとおり、オペランドがNULLでないかぎり、NOTはオペランドの反対の値を戻します。NULLは値を持たないため、NOT NULLNULLを戻します。(例2-37では、例2-35print_booleanプロシージャを起動します。)

例2-38では、xyが等しくないため、一連の文が実行されることが予測されます。ただし、NULL値は予測不可能です。そのため、xyが等しいかどうかは不明です。したがって、IF条件はNULLになり、一連の文は実行されずにバイパスされます。

例2-39では、abが等しいため、一連の文が実行されることが予測されます。ただし、等号条件が成立するかどうかは不明であるため、IF条件はNULLになり、一連の文は実行されずにバイパスされます。

例2-40では、2つのIF文は等しく見えます。ただし、xyのどちらかがNULLの場合、1番目のIF文はyの値をhighに代入しますが、2番目のIF文はxの値をhighに代入します。

例2-41では、例2-35print_booleanプロシージャを3回起動します。3回目と1回目の起動は論理的に等しく、3回目の起動は読みやすさを向上させただけです。2番目の起動では、カッコによって演算の順序が変更されています。

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

例2-35 AND演算子

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

例2-36 OR演算子

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

例2-37 NOT演算子

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

例2-38 等しくない比較での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.

例2-39 等しい比較での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

例2-40 NULLと等しいNOT NULL

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

例2-41 論理演算子の演算順序の変更

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は結果が判別できた時点でただちに式の評価を停止します。

そのため、評価を続ければエラーになるような式でも書くことができます。

例2-42では、OR式で0(ゼロ)による除算エラーが発生するのを短絡評価によって回避しています。on_handの値が0(ゼロ)の場合、左のオペランドはTRUEになるため、PL/SQLは右のオペランドを評価しません。PL/SQLによりOR演算子を適用する前に両方のオペランドを評価した場合には、右のオペランドは0による除算エラーになります。

例2-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を使用します。次の例を参照してください。

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

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

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

関係演算子

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

表2-5 関係演算子

演算子 意味

=

等しい

<>, !=, ~=, ^=

等しくない

<

より小さい

>

より大きい

<=

より小さいか、等しい

>=

より大きいか、等しい

ここでのトピック

算術比較

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

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

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

この例では、例2-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
ブール比較

定義によれば、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(ゼロ)個以上の文字を表します。

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

関連項目:

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

  • LIKEと類似したREGEXP_LIKEの使用の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

例2-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

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

例2-46 式でのBETWEEN演算子

この例では、例2-35print_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)TRUEを戻すのは、xsetのメンバーと等しい場合のみです。

関連項目:

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

例2-47 式でのIN演算子

この例では、例2-35print_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
 

例2-48 NULL値を含む集合でのIN演算子

この例は、setNULL値が含まれている場合に発生する状況を示しています。ここでは、例2-35print_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値(—TRUEFALSEまたはNULL)を戻す式のことです。

最も単純なBOOLEAN式は、1個のBOOLEANリテラル、定数または変数です。次のものもBOOLEAN式です。

NOT boolean_expression
boolean_expression relational_operator boolean_expression
boolean_expression { AND | OR } boolean_expression

関係演算子のリストは、表2-5を参照してください。BOOLEAN式の構文の詳細は、「boolean_expression ::=」を参照してください。

通常、BOOLEAN式は、制御文(「PL/SQLの制御文」を参照)およびDML文のWHERE句で条件として使用します。

BOOLEAN変数自体を条件として使用できますが、TRUE値またはFALSE値と比較する必要はありません。

例2-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_1 THEN result_1
WHEN selector_value_2 THEN result_2
...
WHEN selector_value_n THEN result_n
[ ELSE
  else_result ]
END

selectorは式です(通常は1つの変数)。selector_valueresultは、それぞれリテラルまたは式にすることができます。少なくとも1つのresultはリテラルのNULLではない必要があります。

単純なCASE式は、selector_valueselectorと一致した最初のresultを戻します。残りの式は評価されません。selectorと一致するselector_valueがない場合、CASE式は、else_resultが存在するとそれを戻し、存在しないとNULLを戻します。

関連項目:

構文の詳細は、「simple_case_expression ::=」を参照してください

例2-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

例2-51 WHEN NULLを使用した単純なCASE式

この例に示すように、selectorの値がNULLの場合、WHEN NULLでは一致させることができません。

かわりに、例2-53に示すように、検索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

検索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 ::=」を参照してください

例2-52 検索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)

例2-53 WHEN ... IS NULLを使用した検索CASE式

この例では、検索CASE式を使用して、例2-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など)

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

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

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

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

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

  • XMLファンクション(APPENDCHILDXMLEXISTSNODEなど)

  • 次の変換ファンクション:

    • BIN_TO_NUM

  • その他の該当するファンクション:

    • CUBE_TABLE

    • DATAOBJ_TO_PARTITION

    • LNNVL

    • NVL2

    • 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の値に対して実行可能です。

エラー・レポート・ファンクション

PL/SQLには、PL/SQL例外処理コードで使用するためのSQLCODESQLERRMの2つのエラー・レポート・ファンクションがあります。

詳細は、「SQLCODEファンクション」および「SQLERRMファンクション」を参照してください。

SQLCODEまたはSQLERRMファンクションは、SQL文では使用できません。

条件付きコンパイル

条件付きコンパイルを使用すると、ソース・テキストを削除することなく、PL/SQLアプリケーションの機能をカスタマイズできます。

たとえば、次のことが可能です。

  • 最新のデータベース・リリースで新機能を使用し、古いデータベース・リリースでアプリケーションを実行する場合にそれらの新機能を無効化することができます。

  • 開発環境でデバッグ文またはトレース文をアクティブ化し、本番サイトでアプリケーションを実行する場合にそれらの文を隠ぺいすることができます。

ここでのトピック

条件付きコンパイルの動作方法

注意:

条件付きコンパイル機能および関連するPL/SQLパッケージは、Oracle Database 10gリリース1(10.1.0.4)以上で使用可能です。

条件付きコンパイルでは、IF文に似た選択ディレクティブを使用して、コンパイルするソース・テキストを選択します。通常、選択ディレクティブの条件には問合せディレクティブが含まれています。エラー・ディレクティブは、ユーザー定義のエラーを呼び出します。すべての条件付きコンパイル・ディレクティブは、プリプロセッサ制御トークンとPL/SQLテキストで構成されています。

ここでのトピック

プリプロセッサ制御トークン

プリプロセッサ制御トークンによって、PL/SQLユニットがコンパイルされる前に処理されるコードが識別されます。

構文

$plsql_identifier

$plsql_identifierの間に空白を入れることはできません。

文字$plsql_identifier内でも使用できますが、そこでは特別な意味を持ちません。

次のプリプロセッサ制御トークンは予約されています。

  • $IF

  • $THEN

  • $ELSE

  • $ELSIF

  • $ERROR

plsql_identifierの詳細は、「識別子」を参照してください。

選択ディレクティブ

選択ディレクティブは、コンパイルするソース・テキストを選択します。

構文

$IF boolean_static_expression $THEN
   text
[ $ELSIF boolean_static_expression $THEN
   text
]...
[ $ELSE
   text
$END
]

boolean_static_expressionの構文の詳細は、「静的なブール式」を参照してください。textは任意ですが、通常は文(「statement ::=」を参照)またはエラー・ディレクティブ(「エラー・ディレクティブ」を参照)です。

選択ディレクティブは、いずれかの静的なBOOLEAN式の値がTRUEであるか、またはすべての式が処理されるまで、使用されている順に式を評価します。いずれかの式の値がTRUEの場合、そのテキストがコンパイルされますが、残りの式は評価されず、そのテキストは分析されません。値がTRUEの式がなく、$ELSEが存在する場合は、そのテキストがコンパイルされますが、存在しない場合は、どのテキストもコンパイルされません。

選択ディレクティブの例は、「条件付きコンパイルの例」を参照してください。

関連項目:

選択ディレクティブと同じロジックを持つIF文の詳細は、「条件付き選択文」を参照してください

エラー・ディレクティブ

エラー・ディレクティブは、コンパイル時にユーザー定義のエラー・メッセージを生成します。

構文

$ERROR varchar2_static_expression $END

次のコンパイル時のエラー・メッセージを生成します。stringvarchar2_static_expressionの値です。

PLS-00179: $ERROR: string

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

エラー・ディレクティブの使用例は、例2-58を参照してください。

問合せディレクティブ

問合せディレクティブは、コンパイル環境の情報を提供します。

構文

$$name

name(引用符で囲まれていないPL/SQL識別子)の詳細は、「識別子」を参照してください。

通常、問合せディレクティブは、選択ディレクティブのboolean_static_expressionで使用しますが、その型の変数またはリテラルを使用できるすべての場所で使用できます。また、通常のPL/SQLでは(変数ではなく)リテラルのみ使用可能な場所でも使用できます(たとえば、VARCHAR2変数のサイズを指定するために使用できます)。

ここでのトピック

事前定義の問合せディレクティブ

事前定義の問合せディレクティブは、次のとおりです。

  • $$PLSQL_LINE

    現行のPL/SQLユニットでディレクティブが使用されるソース行の番号を値として持つPLS_INTEGERリテラル。選択ディレクティブの$$PLSQL_LINEの例を次に示します。

    $IF $$PLSQL_LINE = 32 $THEN ...
    
  • $$PLSQL_UNIT

    現行のPL/SQLユニットの名前を持つVARCHAR2リテラル。現行のPL/SQLユニットが無名ブロックの場合、$$PLSQL_UNITの値はNULL値になります。

  • $$PLSQL_UNIT_OWNER

    現行のPL/SQLユニットの所有者を持つVARCHAR2リテラル。現行のPL/SQLユニットが無名ブロックの場合、$$PLSQL_UNIT_OWNERの値はNULL値になります。

  • $$PLSQL_UNIT_TYPE

    現行のPL/SQLユニットのタイプを持つVARCHAR2リテラル。ANONYMOUS BLOCKFUNCTIONPACKAGEPACKAGE BODYPROCEDURETRIGGERTYPEまたはTYPE BODYのいずれか。無名ブロックまたは非DMLトリガー内では、$$PLSQL_UNIT_TYPEの値はANONYMOUS BLOCKになります。

  • $$plsql_compilation_parameter

    名前plsql_compilation_parameterは、PL/SQLコンパイル・パラメータ(PLSCOPE_SETTINGSなど)です。これらのパラメータの詳細は、表1-2を参照してください。

選択ディレクティブには静的なBOOLEAN式が必要なため、VARCHAR2比較で次のような$$PLSQL_UNIT$$PLSQL_UNIT_OWNERまたは$$PLSQL_UNIT_TYPEは使用できません。

$IF $$PLSQL_UNIT = 'AWARD_BONUS' $THEN ...
$IF $$PLSQL_UNIT_OWNER IS HR $THEN ...
$IF $$PLSQL_UNIT_TYPE IS FUNCTION $THEN ...

ただし、前述のディレクティブをNULLと比較することはできます。次に例を示します。

$IF $$PLSQL_UNIT IS NULL $THEN ...
$IF $$PLSQL_UNIT_OWNER IS NOT NULL $THEN ...
$IF $$PLSQL_UNIT_TYPE IS NULL $THEN ...

例2-54 事前定義の問合せディレクティブ

この例のSQL*Plusスクリプトでは、複数の事前定義の問合せディレクティブをPLS_INTEGERおよびVARCHAR2リテラルとして使用し、値がどのように代入されるかを示しています。

SQL> CREATE OR REPLACE PROCEDURE p
  2  AUTHID DEFINER IS
  3    i PLS_INTEGER;
  4  BEGIN
  5    DBMS_OUTPUT.PUT_LINE('Inside p');
  6    i := $$PLSQL_LINE;
  7    DBMS_OUTPUT.PUT_LINE('i = ' || i);
  8    DBMS_OUTPUT.PUT_LINE('$$PLSQL_LINE = ' || $$PLSQL_LINE);
  9    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT = ' || $$PLSQL_UNIT);
 10    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT_OWNER = ' || $$PLSQL_UNIT_OWNER);
 11    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT_TYPE = ' || $$PLSQL_UNIT_TYPE);
 12  END;
 13  /
 
Procedure created.
 
SQL> BEGIN
  2    p;
  3    DBMS_OUTPUT.PUT_LINE('Outside p');
  4    DBMS_OUTPUT.PUT_LINE('$$PLSQL_LINE = ' || $$PLSQL_LINE);
  5    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT = ' || $$PLSQL_UNIT);
  6    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT_OWNER = ' || $$PLSQL_UNIT_OWNER);
  7    DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT_TYPE = ' || $$PLSQL_UNIT_TYPE);
  8  END;
  9  /

結果:

Inside p
i = 6
$$PLSQL_LINE = 8
$$PLSQL_UNIT = P
$$PLSQL_UNIT_OWNER = HR
$$PLSQL_UNIT_TYPE = PROCEDURE
Outside p
$$PLSQL_LINE = 4
$$PLSQL_UNIT =
$$PLSQL_UNIT_OWNER =
$$PLSQL_UNIT_TYPE = ANONYMOUS BLOCK
 
PL/SQL procedure successfully completed.

例2-55 PL/SQLコンパイル・パラメータの値の表示

この例では、PL/SQLコンパイル・パラメータの現在の値を表示します。

注意:

SQL*Plus環境では、SHOW PARAMETERSコマンドを使用して、PL/SQLコンパイル・パラメータを含む初期化パラメータの現在の値を表示できます。SHOWコマンドとPARAMETERSオプションの詳細は、『SQL*Plusユーザーズ・ガイドおよびリファレンス』を参照してください。

BEGIN
  DBMS_OUTPUT.PUT_LINE('$$PLSCOPE_SETTINGS = '     || $$PLSCOPE_SETTINGS);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_CCFLAGS = '        || $$PLSQL_CCFLAGS);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_CODE_TYPE = '      || $$PLSQL_CODE_TYPE);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_OPTIMIZE_LEVEL = ' || $$PLSQL_OPTIMIZE_LEVEL);
  DBMS_OUTPUT.PUT_LINE('$$PLSQL_WARNINGS = '       || $$PLSQL_WARNINGS);
  DBMS_OUTPUT.PUT_LINE('$$NLS_LENGTH_SEMANTICS = ' || $$NLS_LENGTH_SEMANTICS);
END;
/

結果:

$$PLSCOPE_SETTINGS = IDENTIFIERS:NONE
$$PLSQL_CCFLAGS =
$$PLSQL_CODE_TYPE = INTERPRETED
$$PLSQL_OPTIMIZE_LEVEL = 2
$$PLSQL_WARNINGS = ENABLE:ALL
$$NLS_LENGTH_SEMANTICS = BYTE
問合せディレクティブへの値の代入

PLSQL_CCFLAGSコンパイル・パラメータを使用して、問合せディレクティブに値を代入できます。

次に例を示します。

ALTER SESSION SET PLSQL_CCFLAGS = 
  'name1:value1, name2:value2, ... namen:valuen'

それぞれのvalueは、BOOLEANリテラル(TRUEFALSEまたはNULL)、あるいはPLS_INTEGERリテラルである必要があります。valueのデータ型によって、nameのデータ型が決まります。

同じデータ型または異なるデータ型の値を指定して同じnameを複数回使用できます。先に行った代入は、後で行った代入によってオーバーライドされます。たとえば、次のコマンドでは、$$flagの値は5、データ型はPLS_INTEGERに設定されます。

ALTER SESSION SET PLSQL_CCFLAGS = 'flag:TRUE, flag:5'

コンパイル・パラメータを含む事前定義の問合せディレクティブに値を代入する場合、PLSQL_CCFLAGSは使用しないことをお薦めします。コンパイル・パラメータに値を代入する場合は、ALTER SESSION文を使用することをお薦めします。

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

注意:

PLSQL_CCFLAGSのコンパイル時の値は、ストアドPL/SQLユニットのメタデータとともに格納されているため、ユニットを明示的に再コンパイルするときにその値を再利用できます。詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。

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

例2-56 PLSQL_CCFLAGSによるそれ自体への値の代入

この例では、PLSQL_CCFLAGSを使用して、ユーザー定義の問合せディレクティブ$$Some_Flagに値を代入し、さらに、(推奨されてはいませんが)それ自体にも値を代入します。先に行った代入は後で行った代入によってオーバーライドされるため、$$Some_Flagの結果の値は2になり、PLSQL_CCFLAGSの結果の値はALTER SESSION文によって代入される値('Some_Flag:1, Some_Flag:2, PLSQL_CCFlags:99')ではなく、それ自体に代入される値(99)になります。

ALTER SESSION SET
PLSQL_CCFlags = 'Some_Flag:1, Some_Flag:2, PLSQL_CCFlags:99'
/
BEGIN
  DBMS_OUTPUT.PUT_LINE($$Some_Flag);
  DBMS_OUTPUT.PUT_LINE($$PLSQL_CCFlags);
END;
/

結果:

2
99
解決できない問合せディレクティブ

ソース・テキストがラップされていない場合、問合せディレクティブの値を決定できないときにPL/SQLから警告が発行されます。

問合せディレクティブ($$name)を解決できず、ソース・テキストがラップされていない場合は、PL/SQLにより警告PLW-6003が発行され、未解決の問合せディレクティブの値としてNULLが代入されます。ソース・テキストがラップされている場合は、未解決の問合せディレクティブが示されないように、警告メッセージが無効になります。

PL/SQLソース・テキストのラップの詳細は、「PL/SQLのソース・テキストのラップ」を参照してください。

静的な式

静的な式は、値がコンパイル時に決定される式です。文字の比較、変数またはファンクションの起動は含まれていません。静的な式は、条件付きコンパイル・ディレクティブで使用できる唯一の式です。

ここでのトピック

静的なPLS_INTEGER式

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

  • PLS_INTEGERリテラル

    リテラルの詳細は、「リテラル」を参照してください。

  • PLS_INTEGER静的定数

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

  • NULL

関連項目:

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

静的なブール式

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

  • 最大サイズが32,767バイトである文字列リテラル

    リテラルの詳細は、「リテラル」を参照してください。

  • NULL

  • TO_CHAR(x)(xは静的なPLS_INTEGER式)

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

  • TO_CHAR(x, f, n)(xは静的なPLS_INTEGER式で、fnは静的な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リファレンス』を参照してください。

例2-57では、パッケージmy_debugで静的定数debugおよびtraceを定義し、複数のPL/SQLユニットでのデバッグおよびトレースを制御します。プロシージャmy_proc1ではdebugのみが使用され、プロシージャmy_proc2ではtraceのみが使用されますが、いずれのプロシージャもこのパッケージに依存しています。ただし、再コンパイルされるコードが異ならない場合もあります。たとえば、debugの値をFALSEに変更しただけで2つのプロシージャを再コンパイルすると、my_proc1でコンパイルされるコードは変更されますが、my_proc2でコンパイルされるコードは変更されません。

関連項目:

  • 定数の宣言の一般情報は、「定数の宣言」を参照してください

  • パッケージの詳細は、「PL/SQLパッケージ」を参照してください

  • スキーマ・オブジェクトの依存性の詳細は、『Oracle Database開発ガイド』を参照してください。

例2-57 静的定数

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;
/
DBMS_DB_VERSIONパッケージ

DBMS_DB_VERSIONパッケージでは、Oracleバージョン番号、およびOracleのバージョンに基づいて条件付きコンパイルを簡単に選択する場合に有効なその他の情報を指定します。

DBMS_DB_VERSIONパッケージでは、次の静的定数が提供されます。

  • PLS_INTEGER定数VERSIONは、現行のOracle Databaseのバージョンを識別します。

  • PLS_INTEGER定数RELEASEは、現行のOracle Databaseのリリース番号を識別します。

  • VER_LE_v形式のBOOLEAN定数の値はそれぞれ、データベース・バージョンがv以下の場合にTRUEになり、それ以外の場合はFALSEになります。

  • VER_LE_v_r形式のBOOLEAN定数の値はそれぞれ、データベース・バージョンがv以下でリリースがr以下の場合にTRUEになり、それ以外の場合はFALSEになります。

DBMS_DB_VERSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

条件付きコンパイルの例

選択およびユーザー定義の問合せディレクティブを使用した条件付きコンパイルの例です。

例2-58 データベース・バージョンを確認するコード

この例では、データベース・バージョンおよびリリースがOracle Database 10gリリース2より前の場合はエラー・メッセージを生成し、それ以外の場合は、バージョンおよびリリースがサポート対象であるというメッセージを表示してOracle Database 10gリリース2から使用可能になったCOMMIT文を使用します。

BEGIN
  $IF DBMS_DB_VERSION.VER_LE_10_1 $THEN  -- selection directive begins
    $ERROR 'unsupported database release' $END  -- error directive
  $ELSE
    DBMS_OUTPUT.PUT_LINE (
      'Release ' || DBMS_DB_VERSION.VERSION || '.' ||
      DBMS_DB_VERSION.RELEASE || ' is supported.'
    );
  -- This COMMIT syntax is newly supported in 10.2:
  COMMIT WRITE IMMEDIATE NOWAIT;
  $END  -- selection directive ends
END;
/
 

結果:

Release 12.1 is supported.

例2-59 異なるデータベース・バージョンに対する異なるコードのコンパイル

この例では、ユーザー定義の問合せディレクティブ$$my_debugおよび$$my_tracingに値を設定し、条件付きコンパイルを使用します。

  • パッケージmy_pkgの仕様部で、サブタイプmy_realのベース型を判断します(BINARY_DOUBLEは、Oracle Databaseバージョン10g以上でのみ使用できます)。

  • パッケージmy_pkgの本体で、異なるデータベース・バージョンに対してmy_piおよびmy_eの値を別々に計算します

  • プロシージャcircle_areaで、問合せディレクティブ$$my_debugの値がTRUEの場合のみに一部のコードをコンパイルします。

ALTER SESSION SET PLSQL_CCFLAGS = 'my_debug:FALSE, my_tracing:FALSE';
 
CREATE OR REPLACE PACKAGE my_pkg AUTHID DEFINER AS
  SUBTYPE my_real IS
    $IF DBMS_DB_VERSION.VERSION < 10 $THEN
      NUMBER;
    $ELSE
      BINARY_DOUBLE;
    $END
  
  my_pi my_real;
  my_e  my_real;
END my_pkg;
/
 
CREATE OR REPLACE PACKAGE BODY my_pkg AS
BEGIN
  $IF DBMS_DB_VERSION.VERSION < 10 $THEN
    my_pi := 3.14159265358979323846264338327950288420;
    my_e  := 2.71828182845904523536028747135266249775;
  $ELSE
    my_pi := 3.14159265358979323846264338327950288420d;
    my_e  := 2.71828182845904523536028747135266249775d;
  $END
END my_pkg;
/
 
CREATE OR REPLACE PROCEDURE circle_area(radius my_pkg.my_real) AUTHID DEFINER IS
  my_area       my_pkg.my_real;
  my_data_type  VARCHAR2(30);
BEGIN
  my_area := my_pkg.my_pi * (radius**2);
  
  DBMS_OUTPUT.PUT_LINE
    ('Radius: ' || TO_CHAR(radius) || ' Area: ' || TO_CHAR(my_area));
  
  $IF $$my_debug $THEN
    SELECT DATA_TYPE INTO my_data_type
    FROM USER_ARGUMENTS
    WHERE OBJECT_NAME = 'CIRCLE_AREA'
    AND ARGUMENT_NAME = 'RADIUS';
 
    DBMS_OUTPUT.PUT_LINE
      ('Data type of the RADIUS argument is: ' || my_data_type);
  $END
END;
/

CALL DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE
 ('PACKAGE', 'HR', 'MY_PKG');

結果:

PACKAGE my_pkg AUTHID DEFINER AS
SUBTYPE my_real IS
BINARY_DOUBLE;
my_pi my_real;
my_e my_real;
END my_pkg;
 
Call completed.

処理後のソース・テキストの取得と出力

DBMS_PREPROCESSORパッケージでは、処理後の形式でPL/SQLのソース・テキストを取得して出力するサブプログラムが提供されます。

DBMS_PREPROCESSORパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

例2-60 処理後のソース・テキストの表示

この例では、DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCEプロシージャを起動して、「例2-59」my_pkgの処理後の形式を印刷します。処理後のテキストに含まれない「例2-59」のコードの行は、空白行として表示されます。

CALL DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE (
  'PACKAGE', 'HR', 'MY_PKG'
);

結果:

PACKAGE my_pkg AUTHID DEFINERs AS
SUBTYPE my_real IS
BINARY_DOUBLE;
my_pi my_real;
my_e my_real;
END my_pkg;

条件付きコンパイル・ディレクティブの制限

条件付きコンパイル・ディレクティブには、次のセマンティクスの制約が適用されます。

条件付きコンパイル・ディレクティブは、(「CREATE TYPE文」で作成した)スキーマ・レベルのユーザー定義型では使用できません。次の型仕様部で、依存する型の属性構造と依存する表の列構造を決定する、型の属性構造を指定します。

注意:

条件付きコンパイル・ディレクティブを使用して型の属性構造を変更すると、依存オブジェクトが非同期になったり、依存表がアクセス不可になる場合があります。型の属性構造は、「ALTER TYPE文」を使用してのみ変更することをお薦めします。ALTER TYPE文は、変更を依存オブジェクトまで伝播します。

ストアドPL/SQLユニットまたは無名ブロック内の最初の条件付きコンパイル・ディレクティブの位置について、SQLパーサーでは次の制限があります。

  • パッケージ仕様部、パッケージ本体、型本体および仮パラメータがないスキーマ・レベルのサブプログラムでは、キーワードISまたはASの前に最初の条件付きコンパイル・ディレクティブを配置することはできません。

  • 1つ以上の仮パラメータを持つスキーマ・レベルのサブプログラムでは、サブプログラム名の後の左カッコの前に最初の条件付きコンパイル・ディレクティブを配置することはできません。

    正しい例を次に示します。

    CREATE OR REPLACE PROCEDURE my_proc (
      $IF $$xxx $THEN i IN PLS_INTEGER $ELSE i IN INTEGER $END
    ) IS BEGIN NULL; END my_proc;
    /
    
  • トリガーまたは無名ブロックでは、キーワードDECLAREまたはBEGIN(いずれか先に使用されている方)の前に最初の条件付きコンパイル・ディレクティブを配置することはできません。

SQLパーサーでは、無名ブロックでプレースホルダが使用される場合、そのプレースホルダは条件付きコンパイル・ディレクティブで使用できないという制限もあります。次に例を示します。

BEGIN
  :n := 1; -- valid use of placeholder
  $IF ... $THEN
    :n := 1; -- invalid use of placeholder
$END