2 PL/SQL言語の基礎
PL/SQL言語の基本コンポーネントについて説明します。
2.1 キャラクタ・セット
PL/SQLで処理したりデータベースに格納する文字データはすべて、一連のバイトで表現する必要があります。単一の文字をバイトで表現したものを文字コードと呼びます。文字コードのセットをキャラクタ・セットと呼びます。
すべてのOracle Databaseでは、データベース・キャラクタ・セットと各国語キャラクタ・セットがサポートされています。また、PL/SQLでも同様に、これらのキャラクタ・セットがサポートされています。このマニュアルでは、データベース・キャラクタ・セットおよび各国語キャラクタ・セットをPL/SQLで使用する方法を説明します。
ここでのトピック
関連項目:
キャラクタ・セットの概要は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
2.1.1 データベース・キャラクタ・セット
PL/SQLでは、データベース・キャラクタ・セットを使用して次のものを表現します。
-
PL/SQLユニットの格納済ソース・テキスト
PL/SQLユニットの詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。
-
CHAR
、VARCHAR2
、CLOB
およびLONG
の各データ型の文字値これらのデータ型の詳細は、「SQLデータ型」を参照してください。
データベース・キャラクタ・セットは、サポートされている各文字を特定の1バイトにマッピングするシングルバイト、またはサポートされている各文字を一連の1、2、3または4バイトにマッピングする可変幅マルチバイトのいずれかで構成されます。1つの文字コードに含まれる最大バイト数はキャラクタ・セットによって異なります。
すべてのデータベース・キャラクタ・セットには、次の基本文字が含まれます。
-
ラテン文字(AからZおよびaからz)
-
10進数(0から9)
-
記号文字(表2-1を参照)
-
空白文字(空白、タブおよび改行およびキャリッジ・リターン)
基本文字のみを使用するPL/SQLソース・テキストは、すべてのデータベースで格納およびコンパイルできます。基本文字以外の文字を使用するPL/SQLソース・テキストは、その文字をサポートするデータベース・キャラクタ・セットが設定されたデータベースのみで格納およびコンパイルできます。
表2-1 すべてのデータベース・キャラクタ・セットに含まれている記号文字
記号 | 名前 |
---|---|
|
左丸カッコ |
|
右丸カッコ |
|
左山カッコ |
|
右山カッコ |
|
プラス記号 |
|
ハイフンまたはマイナス記号 |
|
アスタリスク |
|
スラッシュ |
|
等号 |
|
カンマ |
|
セミコロン |
|
コロン |
|
ピリオド |
|
感嘆符 |
|
疑問符 |
|
アポストロフィ(一重引用符) |
" |
引用符(二重引用符) |
|
アットマーク |
|
パーセント記号 |
|
シャープ記号 |
|
ドル記号 |
|
アンダースコア |
|
縦棒 |
関連項目:
データベース・キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
2.1.2 各国語キャラクタ・セット
PL/SQLでは、各国語キャラクタ・セットを使用して、NCHAR
、NVARCHAR2
およびNCLOB
の各データ型の文字値を表現します。
関連項目:
-
これらのデータ型の詳細は、「SQLデータ型」を参照してください
-
各国語キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
2.2 字句単位
PL/SQLの字句単位(デリミタ、識別子、リテラル、プラグマおよびコメント)は、PL/SQLの最小の個別構成要素です。
ここでのトピック
2.2.1 デリミタ
デリミタは、PL/SQLで特別な意味を持つ文字、または文字の組合せです。
デリミタの中にデリミタ以外の文字(空白文字を含む)を埋め込まないでください。
表2-2に、PL/SQLのデリミタの概要を示します。
表2-2 PL/SQLのデリミタ
デリミタ | 意味 |
---|---|
|
加算演算子 |
|
代入演算子 |
|
結合演算子 |
|
属性のインジケータ |
|
文字列のデリミタ |
|
構成要素のインジケータ |
|
連結演算子 |
|
除算演算子 |
|
指数演算子 |
|
式またはリストのデリミタ(開始) |
|
式またはリストのデリミタ(終了) |
|
ホスト変数のインジケータ |
|
項目のセパレータ |
|
ラベルのデリミタ(開始) |
|
ラベルのデリミタ(終了) |
|
複数行コメントのデリミタ(開始) |
|
複数行コメントのデリミタ(終了) |
|
乗算演算子 |
|
二重引用符で囲んだ識別子のデリミタ |
|
範囲演算子 |
|
関係演算子(等しい) |
|
関係演算子(等しくない) |
|
関係演算子(等しくない) |
|
関係演算子(等しくない) |
|
関係演算子(等しくない) |
|
関係演算子(より小さい) |
|
関係演算子(より大きい) |
|
関係演算子(以下) |
|
関係演算子(以上) |
|
リモート・アクセスのインジケータ |
|
単一行コメントのインジケータ |
|
文の終了記号 |
|
減算演算子または否定演算子 |
2.2.2 識別子
識別子は、次に示すPL/SQL要素に名前を付けます。
-
定数
-
カーソル
-
例外
-
キーワード
-
ラベル
-
パッケージ
-
予約語
-
サブプログラム
-
型
-
変数
英字かどうかに関係なく、識別子に含まれているすべての文字が意味を持ちます。たとえば、識別子lastname
とlast_name
は別のものとみなされます。
隣接する識別子は、1つ以上の空白またはデリミタ文字で区切る必要があります。
「ユーザー定義の引用識別子」で説明している例を除き、PL/SQLでは識別子の大/小文字が区別されません。たとえば、識別子lastname
、LastName
およびLASTNAME
は同じものとみなされます。
ここでのトピック
2.2.2.1 予約語およびキーワード
予約語とキーワードは、PL/SQLで特別な意味を持つ識別子です。
通常のユーザー定義の識別子として、予約語を使用することはできません。予約語は、ユーザー定義の引用識別子として使用できますが、使用しないことをお薦めします。詳細は、「ユーザー定義の引用識別子」を参照してください。
キーワードは、通常のユーザー定義の識別子として使用できますが、使用しないことをお薦めします。
2.2.2.2 事前定義の識別子
事前定義の識別子は、事前定義のパッケージSTANDARD
で宣言されています。
事前定義の識別子の例としては、例外INVALID_NUMBER
があります。
事前定義の識別子のリストを取得するには、DBAロールを持つユーザーとしてOracle Databaseに接続し、次の問合せを使用します。
SELECT TYPE_NAME FROM ALL_TYPES WHERE PREDEFINED='YES';
事前定義の識別子は、ユーザー定義の識別子として使用できますが、使用しないことをお薦めします。ローカルの宣言はグローバルな宣言をオーバーライドします(「識別子の有効範囲と可視性」を参照)。
2.2.2.3 ユーザー定義の識別子
ユーザー定義の識別子の特性は次のとおりです。
-
データベース・キャラクタ・セットの文字で構成されます。
-
通常の識別子と引用識別子があります。
ヒント:
ユーザー定義の識別子は、意味のあるものにします。たとえば、cost_per_thousand
は意味が明白ですが、cpt
は意味があいまいです。
2.2.2.3.1 通常のユーザー定義の識別子
通常のユーザー定義の識別子の特性は次のとおりです。
-
先頭は英字です。
-
文字、数字および次の記号を使用できます。
-
ドル記号($)
-
シャープ記号(#)
-
アンダースコア(_)
-
-
予約語(表D-1を参照)は使用できません。
データベース・キャラクタ・セットには、文字および数字として分類される文字が定義されています。COMPATIBLEが12.2以上の値に設定されている場合、データベース・キャラクタ・セットでの識別子表現は、128バイトを超えないように定義する必要があります。COMPATIBLEが12.1以下の値に設定されている場合、上限は30バイトです。
通常のユーザー定義の識別子として有効な例を次に示します。
X t2 phone# credit_limit LastName oracle$number money$$$tree SN## try_again_
通常のユーザー定義の識別子として無効な例を次に示します。
mine&yours debit-amount on/off user id
2.2.2.3.2 ユーザー定義の引用識別子
ユーザー定義の引用識別子は、二重引用符で囲まれています。
二重引用符の間には、二重引用符、改行文字およびNULL文字以外の任意の文字をデータベース・キャラクタ・セットから使用できます。たとえば、次の識別子を使用できます。
"X+Y" "last name" "on/off switch" "employee(s)" "*** header info ***"
COMPATIBLEが12.2以上の値に設定されている場合、データベース・キャラクタ・セットでの引用識別子表現は、(二重引用符を除いて)128バイトを超えないように定義する必要があります。COMPATIBLEが12.1以下の値に設定されている場合、上限は30バイトです。
ユーザー定義の引用識別子では大/小文字が区別されますが、例外が1つあります。ユーザー定義の引用識別子から二重引用符を除いたものが有効な通常のユーザー定義の識別子である場合は、その識別子を参照するときの二重引用符は省略可能になり、省略した場合は識別子の大/小文字が区別されなくなります。
お薦めしませんが、予約語をユーザー定義の引用識別子として使用することができます。予約語は有効な通常のユーザー定義の識別子ではないため、識別子は二重引用符で囲む必要があり、大/小文字は常に区別されます。
例2-1 ユーザー定義の引用識別子に対する、大/小文字を区別しない有効な参照
この例では、ユーザー定義の引用識別子"HELLO"
は、二重引用符がなくても有効な通常のユーザー定義の識別子です。したがって、Hello
という参照は有効です。
DECLARE "HELLO" varchar2(10) := 'hello'; BEGIN DBMS_Output.Put_Line(Hello); END; /
結果:
hello
例2-2 ユーザー定義の引用識別子に対する、大/小文字を区別しない無効な参照
この例では、"Hello"
という参照は無効です。これは、二重引用符を付けると識別子の大/小文字が区別されるためです。
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 ユーザー定義の引用識別子としての予約語
この例では、ユーザー定義の引用識別子"BEGIN"
、"Begin"
および"begin"
が宣言されています。BEGIN
、Begin
およびbegin
は同じ予約語を表しますが、"BEGIN"
、"Begin"
および"begin"
は異なる識別子を表します。
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
2.2.3 リテラル
リテラルは、識別子で表現したり他の値から計算する必要がない値です。
たとえば、123
は整数リテラルで'abc'
は文字リテラルですが、1+2
はリテラルではありません。
PL/SQLリテラルにはすべてのSQLリテラル(『Oracle Database SQL言語リファレンス』を参照)およびBOOLEAN
リテラル(SQLにはありません)が含まれます。BOOLEAN
リテラルとは、事前定義の論理値TRUE
、FALSE
または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グローバリゼーション・サポート・ガイド』を参照してください。
2.2.4 プラグマ
プラグマは、コンパイラに対する命令で、コンパイル時に処理されます。
プラグマは予約語PRAGMA
で始まり、プラグマの名前がその後に続きます。一部のプラグマには引数があります。プラグマは、宣言または文の前に記述できます。特定のプラグマにその他の制限が適用される場合もあります。プラグマの影響範囲はプラグマによって異なります。プラグマの名前または引数がコンパイラによって認識されない場合、そのプラグマによる影響はありません。
pragma ::=
プラグマの構文およびセマンティクスの詳細は、次を参照してください。
2.2.5 コメント
PL/SQLコンパイラは、コメントを無視します。コメントを付けておくと、他のアプリケーション開発者がソース・テキストを理解しやすくなります。
一般に、コメントは各コード・セグメントの目的や使用方法を説明するために使用します。また、廃止されたコード部分や作成途中のコード部分をコメントに入れて無効化することもできます。
ここでのトピック
2.2.5.1 単一行コメント
単一行コメントは--
で始まり、その行の終わりまで続きます。
注意:
Oracleプリコンパイラ・プログラムが動的に処理するPL/SQLブロックの中に単一行コメントを置かないでください。Oracleプリコンパイラ・プログラムでは行の終わりを示す文字が無視されるため、単一行コメントはブロックの末尾で終了します。
プログラムのテストまたはデバッグ中に、コード内の1行をコメントにすることによって無効にできます。次に例を示します。
-- DELETE FROM employees WHERE comm_pct IS NULL
例2-6 単一行コメント
この例には、3つの単一行コメントがあります。
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.2.5.2 複数行コメント
複数行コメントは、/*
で始まって*/
で終わり、複数行にまたがることができます。
複数行コメントのデリミタを使用すると、コードの一部分をコメントにできます。その場合、複数行コメントをネストしないように注意してください。複数行コメントに別の複数行コメントを含めることはできません。ただし、複数行コメントに単一行コメントを含めることはできます。たとえば、次の場合、構文エラーが発生します。
/* 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 複数行コメント
この例には、2つの複数行コメントがあります。(SQLファンクションTO_CHAR
は、引数に相当する文字を戻します。TO_CHAR
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)
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.3 宣言
宣言によって、指定されたデータ型の値の記憶域を割り当て、値を参照できるように格納場所に名前を付けます。
オブジェクトは、参照する前に宣言しておく必要があります。宣言は、任意のブロック、サブプログラムまたはパッケージの宣言部で使用できます。
ここでのトピック
変数と定数以外のオブジェクトの宣言の詳細は、「ブロック」のdeclare_section
の構文を参照してください。
2.3.1 NOT NULL制約
スカラー変数または定数(またはコンポジット変数または定数のスカラー・コンポーネント)には、NOT
NULL
制約を指定できます。
NOT
NULL
制約を指定すると、その項目にNULL値を代入できなくなります。この制約は、(データ型から)暗黙的に指定するか、または明示的に指定することができます。
NOT
NULL
を指定するスカラー変数の宣言では、暗黙的か明示的かに関係なく、初期値を変数に代入する必要があります(スカラー変数のデフォルトの初期値はNULL
であるため)。
PL/SQLは長さが0(ゼロ)の文字値をすべてNULL
値とみなします。これには文字関数やブール式によって戻された値が含まれます。
NULL
値かどうかをテストするには、「IS [NOT] NULL演算子」を使用します。
例
例2-9 NOT NULL制約が指定された変数の宣言
この例では、変数acct_id
にNOT
NULL
制約を明示的に指定し、変数a
、b
および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; /
2.3.2 変数の宣言
変数の宣言では、変数の名前とデータ型を常に指定します。
ほとんどのデータ型の場合、変数を宣言するときに初期値を指定することもできます。
変数名は、有効なユーザー定義の識別子である必要があります。
データ型は、任意の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; /
関連トピック
-
スカラー変数の宣言の構文は、「スカラー変数の宣言」を参照してください
-
スカラーのデータ型の詳細は、「PL/SQLのデータ型」を参照してください
-
コンポジット・データ型およびコンポジット変数の詳細は、「PL/SQLのコレクションおよびレコード」を参照してください
2.3.3 定数の宣言
定数は、変更されない値を保持します。
「変数の宣言」の内容は定数の宣言にも当てはまりますが、定数の宣言には必要なものがさらに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; /
関連項目
-
定数の宣言の構文は、「定数の宣言」を参照してください
2.3.4 変数および定数の初期値
変数宣言では、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
がゼロとは異なることを示しています。
DECLARE counter INTEGER; -- initial value is NULL by default BEGIN counter := counter + 1; -- NULL + 1 is still NULLIF counter IS NULL THEN
DBMS_OUTPUT.PUT_LINE('counter is NULL.');
END IF;
END; /
結果:
counter is NULL.
関連トピック
-
定数の連想配列の宣言の詳細は、「連想配列の定数の宣言」を参照してください
-
定数レコードの宣言の詳細は、「レコード定数の宣言」を参照してください
2.3.5 %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
のデータ型とサイズを継承しています。surname
はNOT
NULL
制約を継承しないため、その宣言に初期値は不要です。
DECLARE surname employees.last_name%TYPE; BEGIN DBMS_OUTPUT.PUT_LINE('surname=' || surname); END; /
結果:
surname=
例2-16 別の変数と同じ型の変数の宣言
この例では、変数surname
は変数name
のデータ型、サイズおよびNOT
NULL
制約を継承しています。surname
はname
の初期値を継承しないため、その宣言には初期値(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
2.4 識別子に対する参照
識別子を参照するとき、名前には、単純名、修飾名、リモート名または修飾リモート名を使用します。
識別子の単純名は、その宣言に含まれる名前です。次に例を示します。
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
で宣言された識別子は、同じ名前のローカル識別子を宣言していないかぎり、パッケージ名で修飾しなくても参照できます(「識別子の有効範囲と可視性」を参照)。
2.5 識別子の有効範囲と可視性
識別子の有効範囲とは、その識別子の参照が可能な、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_ratio
とanother_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
2.6 変数への値の代入
変数を宣言した後、次の方法でその変数に値を代入できます。
-
代入文を使用して式の値を代入する方法。
-
SELECT
INTO
文またはFETCH
文を使用して、表の値を割り当てます。 -
OUT
パラメータまたはIN
OUT
パラメータとしてサブプログラムに渡し、サブプログラム内で値を代入する方法。
変数と値のデータ型には、互換性が必要です。あるデータ型を暗黙的に別のデータ型に変換できる場合、この2つのデータ型には互換性があります。暗黙的なデータ変換の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
ここでのトピック
2.6.1 代入文を使用した変数への値の代入
式の値を変数に代入するには、次の形式の代入文を使用します。
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; /
2.6.2 SELECT INTO文を使用した変数への値の代入
SELECT
INTO
文の単純な形式は次のとおりです。
SELECT select_item [, select_item ]... INTO variable_name [, variable_name ]... FROM table_name;
それぞれのselect_item
に、対応する型互換性のあるvariable_name
が必要です。SQLにはBOOLEAN
型がないため、variable_name
はBOOLEAN
変数にはできません。
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
2.6.3 サブプログラムのパラメータとしての変数への値の代入
変数をOUT
パラメータまたはIN
OUT
パラメータとしてサブプログラムに渡し、サブプログラムによってこれらのパラメータに値が代入される場合は、サブプログラムの実行後、その値が変数で保持されます。詳細は、「サブプログラム・パラメータ」を参照してください。
例2-26 IN OUTサブプログラム・パラメータとしての変数への値の代入
この例では、変数new_sal
をプロシージャadjust_salary
に渡します。このプロシージャによって、対応する仮パラメータsal
に値が代入されます。sal
はIN
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
2.6.4 ブール変数への値の代入
BOOLEAN
変数に代入できる値は、TRUE
、FALSE
および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; /
2.7 式
式は、1つ以上の値、演算子、および値に評価されるSQLファンクションの組合せです。
式は常に1つの値を戻します。単純な式には次のものがあります(複雑度の低い順に示しています)。
-
1つの定数または変数(
a
など) -
単項演算子とその1つのオペランド(
-a
など) -
バイナリ演算子とその2つのオペランド(
a+b
など)
オペランドは、変数、定数、リテラル、演算子、ファンクション起動、プレースホルダ、またはその他の式にすることができます。そのため、式は複雑になる場合があります。式の構文の詳細は、「式」を参照してください。
オペランドのデータ型によって、式のデータ型が決まります。式が評価されるたびに、結果としてそのデータ型の値が1つ得られます。結果のデータ型は、式のデータ型です。
2.7.1 連結演算子
連結演算子(||
)は、ある文字列オペランドを別の文字列オペランドに追加します。
連結演算子は、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オペランド
連結演算子は、この例に示すとおり、NULLオペランドを無視します。
BEGIN DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce'); END; /
結果:
applesauce
2.7.2 演算子の優先順位
演算は、単項演算子とオペランド1つか、またはバイナリ演算子とオペランド2つのいずれかです。式内の演算は、演算子の優先順位に応じて評価されます。
表2-3に、優先順位の高い順に演算子を示します。同じ優先順位の演算子は、特に順序を考慮せずに評価されます。
表2-3 演算子の優先順位
演算子 | 演算 |
---|---|
|
指数 |
|
恒等、否定 |
|
乗算、除算 |
|
加算、減算、連結 |
|
比較 |
|
否定 |
|
論理積 |
|
論理和 |
評価の順序を制御するには、例2-30に示すとおり、演算をカッコで囲みます。
カッコがネストされている場合は、最も深くネストされた演算が最初に評価されます。
カッコが評価の順序に影響しない場合でも、カッコを使用してわかりやすくすることができます。
例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 ネストしたカッコを使用した式
この例では、演算(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
例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
2.7.3 論理演算子
論理演算子AND
、OR
、およびNOT
は、3値論理に従います。
AND
とOR
はバイナリ演算子、NOT
は単項演算子です。
表2-4 論理真理値表
x | y | x AND y | x OR y | NOT x |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AND
は、両方のオヘ゜ランドがTRUE
の場合のみ、TRUE
を戻します。
OR
は、どちらか一方のオペランドがTRUE
の場合に、TRUE
を戻します。
NOT
は、オペランドがNULL
の場合を除き、オペランドの反対の値を戻します。NULL
は値を持たないため、NOT
NULL
はNULL
を戻します。
例2-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; /
例2-35 AND演算子
表2-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
例2-36 OR演算子
表2-4およびこの例に示すとおり、一方のオペランドがTRUE
である場合、OR
はTRUE
を戻します。(この例は、例2-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
例2-37 NOT演算子
表2-4およびこの例に示すとおり、オペランドがNULL
でないかぎり、NOT
はオペランドの反対の値を戻します。NULL
は値を持たないため、NOT
NULL
はNULL
を戻します。(この例は、例2-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
例2-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.
例2-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
例2-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; /
例2-41 論理演算子の演算順序の変更
この例では、例2-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
2.7.4 短絡評価
論理式を評価するときに、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.
2.7.5 比較演算子
比較演算子は式と式を比較します。比較の結果は、常にTRUE
、FALSE
またはNULL
のいずれかです。
一方の式の値がNULL
の場合、比較の結果もNULL
になります。
比較演算子は、次のとおりです。
注意:
文字の比較は、実行時に変更可能なNLSパラメータ設定に影響を受けます。したがって、文字の比較は実行時に評価されるので、同じ文字の比較を行っても、タイミングによっては異なる値になることがあります。文字の比較に影響するNLSパラメータの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
注意:
比較演算子にCLOB
値を使用すると、一時的なLOB値が作成される場合があります。一時表領域がこのような値を処理できる大きさであることを確認してください。
2.7.5.2 関係演算子
この表は、関係演算子の概要を示しています。
表2-5 関係演算子
演算子 | 意味 |
---|---|
|
等しい |
|
等しくない |
|
次より小さい |
|
次より大きい |
|
<= |
|
以上または同等 |
ここでのトピック
2.7.5.2.1 算術比較
片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。
実数は近似値として格納されるため、等しいかどうかの比較をすることをお薦めします。
例2-43 式での関係演算子
この例では、例2-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
2.7.5.2.3 文字比較
デフォルトでは、片方の文字のバイナリ値がより大きい場合、その文字はより大きいとみなされます。
たとえば、次の式は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
データ型のセマンティックの違いは、文字の比較に影響します。
詳細は、「値の比較」を参照してください。
2.7.5.3 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
2.7.5.4 BETWEEN演算子
BETWEEN
演算子は、値が指定した範囲内にあるかどうかをテストします。
式x BETWEEN a AND b
の値は、式(x>=a) AND (x<=b)
の値と同じものとして定義されます。式x
は1回のみ評価されます。
関連項目:
BETWEEN
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
例2-46 式でのBETWEEN演算子
この例では、例2-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
2.7.5.5 IN演算子
IN
演算子は、セット・メンバーシップをテストします。
x
IN
(
set
)
は、x
がset
のメンバーに等しい場合にのみTRUE
を戻します。
関連項目:
IN
の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
例2-47 式でのIN演算子
この例では、例2-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
例2-48 NULL値を含む集合でのIN演算子
この例は、set
にNULL
値が含まれている場合に発生する状況を示しています。これは、例2-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
2.7.6 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
関係演算子のリストは、表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; /
2.7.7 CASE式
2.7.7.1 単純な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_value
とresult
は、それぞれリテラルまたは式にすることができます。少なくとも1つのresult
はリテラルのNULL
ではない必要があります。
単純なCASE
式は、selector_value
がselector
と一致した最初のresult
を戻します。残りの式は評価されません。selector
と一致するselector_value
がない場合、CASE
式は、else_result
が存在するとそれを戻し、存在しないとNULL
を戻します。
関連項目:
構文の詳細は、「simple_case_expression ::=」を参照してください
例2-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
例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
2.7.7.2 検索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 ::=」を参照してください
例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
2.7.8 PL/SQL式でのSQLファンクション
PL/SQL式では、次のファンクションを除くすべてのSQLファンクションを使用できます。
-
集計ファンクション(
AVG
、COUNT
など) -
分析ファンクション(
LAG
、RATIO_TO_REPORT
など) -
データ・マイニング・ファンクション(
CLUSTER_ID
、FEATURE_VALUE
など) -
エンコーディング・ファンクションおよびデコーディング・ファンクション(
DECODE
、DUMP
など) -
モデル・ファンクション(
ITERATION_NUMBER
、PREVIOUS
など) -
オブジェクト参照ファンクション(
REF
、VALUE
など) -
XMLファンクション(
APPENDCHILDXML
、EXISTSNODE
など) -
次の変換ファンクション:
-
BIN_TO_NUM
-
-
次のJSON SQL演算子:
-
JSON_ARRAYAGG
-
JSON_OBJAGG
-
JSON_TABLE
-
JSON_TEXTCONTAINS
-
-
次の照合SQL演算子およびファンクション:
-
COLLATE
-
COLLATION
-
NLS_COLLATION_ID
-
NLS_COLLATION_NAME
-
-
その他の該当するファンクション:
-
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
ファンクションの有効な引数であるCHAR
、VARCHAR2
およびLONG
の値と、最大16380バイトのLONG
RAW
およびBLOB
の値に対して実行可能です。
2.7.9 静的な式
静的な式は、値がコンパイル時に決定される式です。文字の比較、変数またはファンクションの起動は含まれていません。静的な式は、条件付きコンパイル・ディレクティブで使用できる唯一の式です。
静的な式の定義
-
式がNULLリテラルである場合、その式は静的です。
-
式が文字、数値またはブールのリテラルである場合、その式は静的です。
-
式が静的定数への参照である場合、その式は静的です。
-
式が$$で始まる条件付きコンパイル変数への参照である場合、その式は静的です。
-
演算子が静的な式で許可されていて、そのオペランドがすべて静的であり、そのオペランドに対する評価時に演算子による例外が発生しない場合、その式は静的です。
表2-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_CHAR
-
TO_NUMBER
-
TRIM
-
TRUNC
-
UPPER
静的な式は、次のサブタイプの宣言で使用できます。
-
文字列型(
VARCHAR2、NCHAR、CHAR、NVARCHAR2、RAW
、およびANSIの同等の型)の長さ -
NUMBER
型およびサブタイプ(FLOAT
など)の位取りおよび精度 -
期間型の精度(年、月、秒)
-
時刻およびタイムスタンプの精度
-
VARRAY
の境界 -
型の宣言における範囲の境界
いずれの場合も、静的な式の結果の型は、宣言された項目のサブタイプと同じであることに加え、コンテキストに対して適切な範囲にある必要があります。
2.7.9.1 静的なPLS_INTEGER式
静的なPLS_INTEGER
式には次のものがあります。
関連項目:
PLS_INTEGER
データ型の詳細は、「PLS_INTEGERおよびBINARY_INTEGERデータ型」を参照してください
2.7.9.2 静的な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
データ型の詳細は、「ブール・データ型」を参照してください
2.7.9.3 静的な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変数」を参照してください
2.7.9.4 静的定数
静的定数は、パッケージ仕様部で次の構文を使用して宣言します。
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開発ガイド』を参照してください。
例2-54 静的定数
この例では、パッケージ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; /
2.8 エラー・レポート・ファンクション
PL/SQLには、PL/SQL例外処理コードで使用するためのSQLCODE
とSQLERRM
の2つのエラー・レポート・ファンクションがあります。
詳細は、「SQLCODEファンクション」および「SQLERRMファンクション」を参照してください。
SQLCODE
またはSQLERRM
ファンクションは、SQL文では使用できません。
2.9 条件付きコンパイル
条件付きコンパイルを使用すると、ソース・テキストを削除することなく、PL/SQLアプリケーションの機能をカスタマイズできます。
たとえば、次のことが可能です。
-
最新のデータベース・リリースで新機能を使用し、古いデータベース・リリースでアプリケーションを実行する場合にそれらの新機能を無効化することができます。
-
開発環境でデバッグ文またはトレース文をアクティブ化し、本番サイトでアプリケーションを実行する場合にそれらの文を隠ぺいすることができます。
ここでのトピック
2.9.1 条件付きコンパイルの動作方法
条件付きコンパイルでは、IF
文に似た選択ディレクティブを使用して、コンパイルするソース・テキストを選択します。
通常、選択ディレクティブの条件には問合せディレクティブが含まれています。エラー・ディレクティブは、ユーザー定義のエラーを呼び出します。すべての条件付きコンパイル・ディレクティブは、プリプロセッサ制御トークンとPL/SQLテキストで構成されています。
ここでのトピック
関連項目:
静的な式2.9.1.1 プリプロセッサ制御トークン
プリプロセッサ制御トークンによって、PL/SQLユニットがコンパイルされる前に処理されるコードが識別されます。
構文
$plsql_identifier
$
とplsql_identifier
の間に空白を入れることはできません。
文字$
はplsql_identifier
内でも使用できますが、そこでは特別な意味を持ちません。
次のプリプロセッサ制御トークンは予約されています。
-
$IF
-
$THEN
-
$ELSE
-
$ELSIF
-
$ERROR
plsql_identifier
の詳細は、「識別子」を参照してください。
2.9.1.2 選択ディレクティブ
選択ディレクティブは、コンパイルするソース・テキストを選択します。
構文
$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
文の詳細は、「条件付き選択文」を参照してください
2.9.1.3 エラー・ディレクティブ
エラー・ディレクティブは、コンパイル時にユーザー定義のエラー・メッセージを生成します。
構文
$ERROR varchar2_static_expression $END
次のコンパイル時のエラー・メッセージを生成します。string
はvarchar2_static_expression
の値です。
PLS-00179: $ERROR: string
varchar2_static_expression
の構文の詳細は、「静的なVARCHAR2式」を参照してください。
エラー・ディレクティブの使用例は、例2-58を参照してください。
2.9.1.4 問合せディレクティブ
問合せディレクティブは、コンパイル環境の情報を提供します。
構文
$$name
name
(引用符で囲まれていないPL/SQL識別子)の詳細は、「識別子」を参照してください。
通常、問合せディレクティブは、選択ディレクティブのboolean_static_expression
で使用しますが、その型の変数またはリテラルを使用できるすべての場所で使用できます。また、通常のPL/SQLでは(変数ではなく)リテラルのみ使用可能な場所でも使用できます(たとえば、VARCHAR2
変数のサイズを指定するために使用できます)。
ここでのトピック
2.9.1.4.1 事前定義の問合せディレクティブ
事前定義の問合せディレクティブは、次のとおりです。
-
$$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
BLOCK
、FUNCTION
、PACKAGE
、PACKAGE
BODY
、PROCEDURE
、TRIGGER
、TYPE
または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-55 事前定義の問合せディレクティブ
この例は、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-56 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
2.9.1.4.2 問合せディレクティブへの値の代入
PLSQL_CCFLAGS
コンパイル・パラメータを使用して、問合せディレクティブに値を代入できます。
次に例を示します。
ALTER SESSION SET PLSQL_CCFLAGS = 'name1:value1, name2:value2, ... namen:valuen'
それぞれのvalue
は、BOOLEAN
リテラル(TRUE
、FALSE
または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-57 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
2.9.1.4.3 解決できない問合せディレクティブ
ソース・テキストがラップされていない場合、問合せディレクティブの値を判別できないと、PL/SQLによって警告が発行されます。
問合せディレクティブ($$
name
)を解決できず、ソース・テキストがラップされていない場合は、PL/SQLにより警告PLW-6003
が発行され、未解決の問合せディレクティブの値としてNULL
が代入されます。ソース・テキストがラップされている場合は、未解決の問合せディレクティブが示されないように、警告メッセージが無効になります。
PL/SQLソース・テキストのラップの詳細は、「PL/SQLのソース・テキストのラップ」を参照してください。
2.9.1.5 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.9.2 条件付きコンパイルの例
選択およびユーザー定義の問合せディレクティブを使用する条件付きコンパイルの例。
例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.
2.9.3 処理後のソース・テキストの取得と出力
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;
2.9.4 条件付きコンパイル・ディレクティブの制限
条件付きコンパイル・ディレクティブは、これらのセマンティクス制限の対象となります。
条件付きコンパイル・ディレクティブは、(「CREATE TYPE文」で作成した)スキーマ・レベルのユーザー定義型では使用できません。次の型仕様部で、依存する型の属性構造と依存する表の列構造を決定する、型の属性構造を指定します。
注意:
条件付きコンパイル・ディレクティブを使用して型の属性構造を変更すると、依存オブジェクトが非同期になったり、依存表がアクセス不可になる場合があります。型の属性構造は、「ALTER TYPE文」を使用してのみ変更することをお薦めします。ALTER
TYPE
文は、変更を依存オブジェクトまで伝播します。
スキーマ・レベルの型の仕様部で条件付きコンパイル・ディレクティブが使用されていると、コンパイラはエラー「PLS-00180: プリプロセッサ・ディレクティブは、このコンテキストでサポートされていません
」を報告します。
すべての条件付きコンパイラの構造はPL/SQLプリプロセッサによって処理されるため、SQLパーサーは、ストアドPL/SQLユニットまたは無名ブロック内の最初の条件付きコンパイル・ディレクティブの場所に対して次の制限を強制します。
-
パッケージ仕様部、パッケージ本体、型本体、スキーマ・レベル・ファンクションおよびスキーマ・レベル・プロシージャには、条件コンパイル・ディレクティブが有効になる前に、ユニット名の識別子の後に少なくとも1つの空白でないPL/SQLトークンがあることが必要です。
注意:
-
PL/SQLのコメント"--"または"/*"は、空白トークンとしてカウントされます。
-
トークンがPL/SQLで無効な場合は、PLS-00103エラーが発行されます。ただし、このルールに違反した状態で条件付きコンパイル・ディレクティブが使用されていると、ORAエラーが生成されます。
例2-61および例2-62では、最初の条件付きコンパイル・ディレクティブが、定義しているユニットの識別子に続く最初のPL/SQLトークンの後にあることを示しています。
-
-
トリガーまたは無名ブロックでは、キーワード
DECLARE
またはBEGIN
(いずれか先に使用されている方)の前に最初の条件付きコンパイル・ディレクティブを配置することはできません。
SQLパーサーでは、無名ブロックでプレースホルダが使用される場合、そのプレースホルダは条件付きコンパイル・ディレクティブで使用できないという制限もあります。次に例を示します。
BEGIN :n := 1; -- valid use of placeholder $IF ... $THEN :n := 1; -- invalid use of placeholder $END
例2-61 パッケージ仕様の定義で使用する条件付きコンパイル・ディレクティブ
この例は、パッケージ仕様の定義で、AUTHID
句の後のキーワードIS
の前に、最初の条件付きコンパイル・ディレクティブを配置する例を示しています。
CREATE OR REPLACE PACKAGE cc_pkg AUTHID DEFINER $IF $$XFLAG $THEN ACCESSIBLE BY(p1_pkg) $END IS i NUMBER := 10; trace CONSTANT BOOLEAN := TRUE; END cc_pkg;
結果:
Package created.
例2-62 サブプログラムの仮パラメータ・リストで使用する条件付きコンパイル・ディレクティブ
この例は、PL/SQLプロシージャ定義の仮パラメータ・リストで、左カッコの後に最初の条件付きコンパイル・ディレクティブが配置されることを示しています。
CREATE OR REPLACE PROCEDURE my_proc ( $IF $$xxx $THEN i IN PLS_INTEGER $ELSE i IN INTEGER $END ) IS BEGIN NULL; END my_proc;
結果:
Procedure created.