この章では、PL/SQL言語の次の点について説明します。
PL/SQLで処理したりデータベースに格納する文字データはすべて、一連のバイトで表現する必要があります。単一の文字をバイトで表現したものを文字コードと呼びます。文字コードのセットをキャラクタ・セットと呼びます。
すべてのOracle Databaseでは、データベース・キャラクタ・セットと各国語キャラクタ・セットがサポートされています。また、PL/SQLでも同様に、これらのキャラクタ・セットがサポートされています。このマニュアルでは、データベース・キャラクタ・セットおよび各国語キャラクタ・セットをPL/SQLで使用する方法を説明します。
ここでのトピック
|
関連項目: キャラクタ・セットの概要は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。 |
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グローバリゼーション・サポート・ガイド』を参照してください。 |
PL/SQLでは、各国語キャラクタ・セットを使用して、NCHAR、NVARCHAR2およびNCLOBの各データ型の文字値を表現します。これらのデータ型の詳細は、「SQLデータ型」を参照してください。
|
関連項目: 各国語キャラクタ・セットの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。 |
PL/SQLの字句単位(デリミタ、識別子、リテラルおよびコメント)は、PL/SQLの最小の個別構成要素です。
ここでのトピック
デリミタは、PL/SQLで特別な意味を持つ文字、または文字の組合せです。デリミタの中にデリミタ以外の文字(空白文字を含む)を埋め込まないでください。
表2-2に、PL/SQLのデリミタの概要を示します。
表2-2 PL/SQLのデリミタ
| デリミタ | 意味 |
|---|---|
|
|
加算演算子 |
|
|
代入演算子 |
|
|
結合演算子 |
|
|
属性のインジケータ |
|
|
文字列のデリミタ |
|
|
構成要素のインジケータ |
|
|
連結演算子 |
|
|
除算演算子 |
|
|
指数演算子 |
|
|
式またはリストのデリミタ(開始) |
|
|
式またはリストのデリミタ(終了) |
|
|
ホスト変数のインジケータ |
|
|
項目のセパレータ |
|
|
ラベルのデリミタ(開始) |
|
|
ラベルのデリミタ(終了) |
|
|
複数行コメントのデリミタ(開始) |
|
|
複数行コメントのデリミタ(終了) |
|
|
乗算演算子 |
|
|
二重引用符で囲んだ識別子のデリミタ |
|
|
範囲演算子 |
|
|
関係演算子(等しい) |
|
|
関係演算子(等しくない) |
|
|
関係演算子(等しくない) |
|
|
関係演算子(等しくない) |
|
|
関係演算子(等しくない) |
|
|
関係演算子(より小さい) |
|
|
関係演算子(より大きい) |
|
|
関係演算子(以下) |
|
|
関係演算子(以上) |
|
|
リモート・アクセスのインジケータ |
|
|
単一行コメントのインジケータ |
|
|
文の終了記号 |
|
|
減算演算子または否定演算子 |
定数
カーソル
例外
キーワード
ラベル
パッケージ
予約語
サブプログラム
型
変数
英字かどうかに関係なく、識別子に含まれているすべての文字が意味を持ちます。たとえば、識別子lastnameとlast_nameは別のものとみなされます。
隣接する識別子は、1つ以上の空白またはデリミタ文字で区切る必要があります。
「ユーザー定義の引用識別子」で説明している例を除き、PL/SQLでは識別子の大/小文字が区別されません。たとえば、識別子lastname、LastNameおよびLASTNAMEは同じものとみなされます。
ここでのトピック
予約語とキーワードは、PL/SQLで特別な意味を持つ識別子です。
通常のユーザー定義の識別子として、予約語を使用することはできません。予約語は、ユーザー定義の引用識別子として使用できますが、使用しないことをお薦めします。詳細は、「ユーザー定義の引用識別子」を参照してください。
キーワードは、通常のユーザー定義の識別子として使用できますが、使用しないことをお薦めします。
事前定義の識別子は、事前定義のパッケージ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-1 ユーザー定義の引用識別子に対する、大/小文字を区別しない有効な参照
DECLARE "HELLO" varchar2(10) := 'hello'; BEGIN DBMS_Output.Put_Line(Hello); END; /
結果:
hello
例2-2の"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では、ユーザー定義の引用識別子"BEGIN"、"Begin"および"begin"が宣言されています。BEGIN、Beginおよびbeginは同じ予約語を表しますが、"BEGIN"、"Begin"および"begin"は異なる識別子を表します。
例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では、二重引用符で囲まずに、予約語であるユーザー定義の引用識別子を参照しています。
例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では、大/小文字の区別を無視して、予約語であるユーザー定義の引用識別子を参照しています。
例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リテラルとは、事前定義の論理値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グローバリゼーション・サポート・ガイド』を参照してください。
PL/SQLコンパイラは、コメントを無視します。コメントを付けておくと、他のアプリケーション開発者がソース・テキストを理解しやすくなります。一般に、コメントは各コード・セグメントの目的や使用方法を説明するために使用します。また、廃止されたコード部分や作成途中のコード部分をコメントに入れて無効化することもできます。
ここでのトピック
|
注意: Oracleプリコンパイラ・プログラムが動的に処理するPL/SQLブロックの中に単一行コメントを置かないでください。Oracleプリコンパイラ・プログラムでは行の終わりを示す文字が無視されるため、単一行コメントはブロックの末尾で終了します。 |
例2-6には、3つの単一行コメントがあります。
例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; /
プログラムのテストまたはデバッグ中に、コード内の1行をコメントにすることによって無効にできます。次に例を示します。
-- DELETE FROM employees WHERE comm_pct IS NULL
複数行コメントは、/*で始まって*/で終わり、複数行にまたがることができます。
例2-7には、2つの複数行コメントがあります。(SQLファンクションTO_CHARは、引数に相当する文字を戻します。TO_CHARの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)
例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
複数行コメントのデリミタを使用すると、コードの一部分をコメントにできます。その場合、複数行コメントをネストしないように注意してください。複数行コメントに別の複数行コメントを含めることはできません。ただし、複数行コメントに単一行コメントを含めることはできます。たとえば、次の場合、構文エラーが発生します。
/* 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-8に示すとおり、字句単位の間に空白文字を挿入できます。多くの場合、これによってソース・テキストが読みやすくなります。
宣言によって、指定されたデータ型の値の記憶域を割り当て、値を参照できるように格納場所に名前を付けます。オブジェクトは、参照する前に宣言しておく必要があります。宣言は、任意のブロック、サブプログラムまたはパッケージの宣言部で使用できます。
ここでのトピック
変数と定数以外のオブジェクトの宣言の詳細は、「ブロック」のdeclare_sectionの構文を参照してください。
変数の宣言では、変数の名前とデータ型を常に指定します。ほとんどのデータ型の場合、変数を宣言するときに初期値を指定することもできます。
変数名は、有効なユーザー定義の識別子である必要があります(「ユーザー定義の識別子」を参照)。
データ型は、任意のPL/SQLデータ型を選択できます。PL/SQLデータ型にはSQLデータ型が含まれます。データ型は、スカラー(内部コンポーネントなし)またはコンポジット(内部コンポーネントあり)のいずれかです。
例2-9では、複数のスカラー・データ型の変数を宣言します。
例2-9 スカラー変数の宣言
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-10では、スカラー・データ型の3つの定数を宣言します。
例2-10 定数の宣言
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制約を指定しないかぎり、初期値はオプションです(詳細は「NOT NULL制約」を参照してください)。定数の宣言では、初期値は必須です。
ブロックまたはサブプログラムに宣言が含まれている場合は、ブロックまたはサブプログラムに制御が渡されるたびに、変数または定数に初期値が代入されます。宣言がパッケージ仕様部にある場合は、(変数または定数がパブリックかプライベートかには関係なく)セッションごとに初期値が変数または定数に代入されます。
初期値を指定するには、代入演算子(:=)またはキーワードDEFAULTを使用し、その後に式を指定します。式には、事前に宣言済の定数と、事前に初期化済の変数を使用できます。
例2-11では、宣言する定数および変数に初期値を代入します。areaの初期値は、事前に宣言済の定数piおよび事前に初期化済の変数radiusに応じて異なります。
例2-11 初期値が指定された変数および定数の宣言
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-12では、変数counterの初期値はデフォルトのNULLです。この例(「IS [NOT] NULL演算子」を使用)が示すとおり、NULLは0(ゼロ)とは異なります。
例2-12 デフォルトでNULLに初期化される変数
DECLARE counter INTEGER; -- initial value is NULL by default BEGIN counter := counter + 1; -- NULL + 1 is still NULLIF counter IS NULL THENDBMS_OUTPUT.PUT_LINE('counter is NULL.');END IF;END; /
結果:
counter is NULL.
スカラー変数または定数(またはコンポジット変数または定数のスカラー・コンポーネント)には、NOT NULL制約を指定できます。NOT NULL制約を指定すると、その項目にNULL値を代入できなくなります。この制約は、(データ型から)暗黙的に指定するか、または明示的に指定することができます。
NOT NULLを指定するスカラー変数の宣言では、暗黙的か明示的かに関係なく、初期値を変数に代入する必要があります(スカラー変数のデフォルトの初期値はNULLであるため)。
例2-13では、変数acct_idにNOT NULL制約を明示的に指定し、変数a、bおよびcにはデータ型から暗黙的に指定します。
例2-13 NOT NULL制約が指定された変数の宣言
DECLARE acct_id INTEGER(4) NOT NULL := 9999; a NATURALN := 9999; b POSITIVEN := 9999; c SIMPLE_INTEGER := 9999; BEGIN NULL; END; /
PL/SQLは長さが0(ゼロ)の文字値をすべてNULL値とみなします。これには文字ファンクションやブール式によって戻された値が含まれます。
例2-14では、すべての変数がNULLに初期化されます。
例2-14 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;
/
NULL値かどうかをテストするには、「IS [NOT] NULL演算子」を使用します。
%TYPE属性を使用すると、事前に宣言されている変数または列と同じデータ型のデータ項目を(データ型を知らなくても)宣言できます。参照先項目の宣言が変更されると、それに応じて参照元項目の宣言も変更されます。
次に宣言の構文を示します。
referencing_item referenced_item%TYPE;
参照元項目および参照先項目にすることができる項目の種類は、「%TYPE属性」を参照してください。
参照元項目は、参照先項目から次のものを継承します。
データ型およびサイズ
制約(参照先項目が列である場合を除く)
参照元項目は、参照先項目の初期値は継承しません。そのため、参照元項目でNOT NULL制約が指定または継承される場合は、参照元項目の初期値を指定する必要があります。
%TYPE属性は、データベースの値を保持する変数を宣言する場合に特に便利です。列と同じ型の変数を宣言する構文は、次のようになります。
variable_name table_name.column_name%TYPE;
例2-15では、変数surnameは、NOT NULL制約が指定されている列employees.last_nameのデータ型とサイズを継承しています。surnameはNOT NULL制約を継承しないため、その宣言に初期値は不要です。
例2-15 列と同じ型の変数の宣言
DECLARE
surname employees.last_name%TYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE('surname=' || surname);
END;
/
結果:
surname=
例2-16では、変数surnameは変数nameのデータ型、サイズおよびNOT NULL制約を継承しています。surnameはnameの初期値を継承しないため、その宣言には初期値(25文字以内)が必要です。
例2-16 別の変数と同じ型の変数の宣言
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でのあいまいな名前の解決方法の詳細は、付録B「PL/SQLの名前解決」を参照してください。
|
注意: パッケージSTANDARDおよびDBMS_STANDARDで宣言された識別子は、同じ名前のローカル識別子を宣言していないかぎり、パッケージ名で修飾しなくても参照できます(「識別子の有効範囲と可視性」を参照)。 |
識別子の有効範囲とは、その識別子の参照が可能な、PL/SQLユニットの領域です。識別子の可視性とは、修飾なしでその識別子の参照が可能な、PL/SQLユニットの領域です。識別子は、自身が宣言されているPL/SQLユニットに対してローカルです。そのユニットにサブユニットがある場合、識別子はサブユニットに対してグローバルです。
サブユニットでグローバル識別子が再宣言されると、そのサブユニット内では両方の識別子が有効範囲内にあることになりますが、ローカル識別子のみが表示されます。サブユニットでグローバル識別子を参照するには、グローバル識別子が宣言されているユニットの名前でグローバル識別子を修飾する必要があります。そのユニットに名前がない場合、サブユニットでグローバル識別子を参照することはできません。
PL/SQLユニットは、あるユニットから同じレベルの他のユニットで宣言されている識別子への参照はできません。そのような識別子は、そのブロックに対してローカルでもグローバルでもないためです。
例2-17に、いくつかの識別子の有効範囲と可視性を示します。最初のサブブロックで、グローバル識別子aが再宣言されています。グローバル変数aを参照するには、最初のサブブロックで、外側のブロックの名前を使用して変数を修飾する必要がありますが、外側のブロックには名前がありません。そのため、最初のサブブロックではグローバル変数aを参照することはできず、参照できるのはローカル変数aのみです。サブブロックは同じレベルにあるため、最初のサブブロックはdを参照できず、2番目のサブブロックはcを参照できません。
例2-17 識別子の有効範囲と可視性
-- 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も参照できます。
例2-18 ブロック・ラベルによる、再宣言されたグローバル識別子の修飾
<<outer>> -- label DECLARE birthdate DATE := '09-AUG-70'; BEGIN DECLARE birthdate DATE := '29-SEP-70'; 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を宣言しています。ファンクションで変数を再宣言します。その後、ファンクションはグローバル変数をプロシージャ名で修飾して参照します。
例2-19 サブプログラム名による識別子の修飾
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
同じPL/SQLユニット内で、同じ識別子を2回宣言することはできません。例2-20に示すとおり、これを行うと、重複する識別子を参照したときにエラーが発生します。
例2-20 同じ有効範囲での重複する識別子
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つの異なるユニットであれば、同じ識別子を宣言できます。その識別子で表される2つのオブジェクトは区別されます。例2-21に示すとおり、1つを変更しても、もう1つに影響はありません。
例2-21 異なるユニットでの同じ識別子の宣言
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を参照します。
例2-22 同じ有効範囲内で同じ名前を持つラベルとサブプログラム
<<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エラーが発生します。
例2-23 複数の重複したラベルを使用するブロック
<<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では、複数の変数を宣言(一部には初期値も指定)してから、代入文を使用して式の値を変数に代入します。
例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 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文を使用して、employee_idが100である従業員の給与の10%にあたる値を変数bonusに代入します。
変数をOUTパラメータまたはIN OUTパラメータとしてサブプログラムに渡し、サブプログラムによってこれらのパラメータに値が代入される場合は、サブプログラムの実行後、その値が変数で保持されます。詳細は、「サブプログラム・パラメータ」を参照してください。
例2-26では、変数new_salをプロシージャadjust_salaryに渡します。このプロシージャによって、対応する仮パラメータsalに値が代入されます。salはIN OUTパラメータであるため、プロシージャの実行終了後、代入された値が変数new_salで保持されます。
例2-26 IN OUTサブプログラム・パラメータとしての変数への値の代入
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変数に代入できる値は、TRUE、FALSEおよびNULLのみです。
例2-27では、BOOLEAN変数doneをデフォルトでNULLに初期化し、リテラル値FALSEを代入して、リテラル値TRUEと比較し、BOOLEAN式の値を代入します。
例2-27 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; /
BOOLEANデータ型の詳細は、「ブール・データ型」を参照してください。
式は常に1つの値を戻します。単純な式には次のものがあります(複雑度の低い順に示しています)。
1つの定数または変数(aなど)
単項演算子とその1つのオペランド(-aなど)
バイナリ演算子とその2つのオペランド(a+bなど)
オペランドは、変数、定数、リテラル、演算子、ファンクション起動、プレースホルダ、またはその他の式にすることができます。そのため、式は複雑になる場合があります。式の構文の詳細は、「式」を参照してください。
オペランドのデータ型によって、式のデータ型が決まります。式が評価されるたびに、結果としてそのデータ型の値が1つ得られます。結果のデータ型は、式のデータ型です。
ここでのトピック
連結演算子(||)は、例2-28に示すとおり、ある文字列オペランドを別の文字列オペランドに追加します。
例2-28 連結演算子
DECLARE x VARCHAR2(4) := 'suit'; y VARCHAR2(4) := 'case'; BEGIN DBMS_OUTPUT.PUT_LINE (x || y); END; /
結果:
suitcase
連結演算子は、例2-29に示すとおり、NULLオペランドを無視します。
例2-29 連結演算子とNULLオペランド
BEGIN
DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce');
END;
/
結果:
applesauce
連結演算子の構文の詳細は、「character_expression ::=」を参照してください。
演算は、単項演算子とオペランド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が算出されます。
例2-31 ネストしたカッコを使用した式
DECLARE
a INTEGER := ((1+2)*(3+4))/7;
BEGIN
DBMS_OUTPUT.PUT_LINE('a = ' || TO_CHAR(a));
END;
/
結果:
a = 3
カッコが評価の順序に影響しない場合でも、例2-32のように、カッコを使用してわかりやすくすることができます。
例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では、より複雑ないくつかの式での演算子の優先順位とカッコの効果を示します。
例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
論理演算子AND、ORおよびNOTは、表2-4に示す3値論理に従います。ANDとORはバイナリ演算子、NOTは単項演算子です。
表2-4 論理真理値表
| x | y | x AND y | x OR y | NOT x |
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例2-34では、BOOLEAN変数の値を出力するprint_booleanというプロシージャを作成します。このプロシージャでは、「IS [NOT] NULL演算子」が使用されます。この章で紹介するいくつかの例で、print_booleanを起動しています。
例2-34 BOOLEAN変数を出力するプロシージャ
CREATE OR REPLACE PROCEDURE print_boolean (
b_name VARCHAR2,
b_value BOOLEAN
) 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-4および例2-35に示すとおり、両方のオペランドがTRUEである場合にのみ、ANDはTRUEを戻します。
例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-4および例2-36に示すとおり、一方のオペランドがTRUEである場合、ORはTRUEを戻します。(例2-36では、例2-35のprint_booleanプロシージャを起動します。)
例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-4および例2-37に示すとおり、オペランドがNULLでないかぎり、NOTはオペランドの反対の値を戻します。NULLは値を持たないため、NOT NULLはNULLを戻します。(例2-37では、例2-35のprint_booleanプロシージャを起動します。)
例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では、xとyが等しくないため、一連の文が実行されることが予測されます。ただし、NULL値は予測不可能です。そのため、xとyが等しいかどうかは不明です。したがって、IF条件は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では、aとbが等しいため、一連の文が実行されることが予測されます。ただし、等号条件が成立するかどうかは不明であるため、IF条件はNULLになり、一連の文は実行されずにバイパスされます。
例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では、2つのIF文は等しく見えます。ただし、xとyのどちらかがNULLの場合、1番目のIF文はyの値をhighに代入しますが、2番目のIF文はxの値をhighに代入します。
例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では、例2-35のprint_booleanプロシージャを3回起動します。3回目と1回目の起動は論理的に等しく、3回目の起動は読みやすさを向上させただけです。2番目の起動では、カッコによって演算の順序が変更されています。
論理式を評価するときに、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.
比較演算子は式と式を比較します。比較の結果は、常にTRUE、FALSEまたはNULLのいずれかです。一方の式の値がNULLの場合、比較の結果もNULLになります。
比較演算子は、次のとおりです。
|
注意: 文字の比較は、実行時に変更可能なNLSパラメータ設定に影響を受けます。したがって、文字の比較は実行時に評価されるので、同じ文字の比較を行っても、タイミングによっては異なる値になることがあります。文字の比較に影響するNLSパラメータの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。 |
IS NULL演算子は、オペランドがNULLの場合はBOOLEAN値TRUEを、NULLではない場合はFALSEを戻します。IS NOT NULL演算子の動作は逆です。NULL値が関係する比較は、常に結果がNULLになります。
値がNULLかどうかをテストするには、IF value IS NULLを使用します。次の例を参照してください。
表2-5に、関係演算子の概要を示します。
ここでのトピック
片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。実数は近似値として格納されるため、等しいかどうかの比較をすることをお薦めします。
例2-43では、例2-35のprint_booleanプロシージャを起動し、関係演算子を使用して算術値を比較する式の値を出力します。
例2-43 式での関係演算子
BEGIN
print_boolean ('(2 + 2 = 4)', 2 + 2 = 4);
print_boolean ('(2 + 2 <> 4)', 2 + 2 <> 4);
print_boolean ('(2 + 2 != 4)', 2 + 2 != 4);
print_boolean ('(2 + 2 ~= 4)', 2 + 2 ~= 4);
print_boolean ('(2 + 2 ^= 4)', 2 + 2 ^= 4);
print_boolean ('(1 < 2)', 1 < 2);
print_boolean ('(1 > 2)', 1 > 2);
print_boolean ('(1 <= 2)', 1 <= 2);
print_boolean ('(1 >= 1)', 1 >= 1);
END;
/
結果:
(2 + 2 = 4) = TRUE (2 + 2 <> 4) = FALSE (2 + 2 != 4) = FALSE (2 + 2 ~= 4) = FALSE (2 + 2 ^= 4) = FALSE (1 < 2) = TRUE (1 > 2) = FALSE (1 <= 2) = TRUE (1 >= 1) = TRUE
定義によれば、TRUEはFALSEよりも大きい値を持ちます。NULLとの比較では、NULLが戻されます。
デフォルトでは、片方の文字のバイナリ値がより大きい場合、その文字はより大きいとみなされます。たとえば、次の式は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データ型のセマンティックの違いは、文字の比較に影響します。詳細は、「値の比較」を参照してください。
片方の日付がより新しい場合、その日付はより大きいとみなされます。たとえば、次の式はTRUEになります。
'01-JAN-91' > '31-DEC-90'
LIKE演算子は、文字、文字列またはCLOB値をパターンと比較し、値がパターンと一致した場合はTRUE、一致しなかった場合はFALSEを戻します。
パターンには、アンダースコア(_)およびパーセント記号(%)の2種類のワイルドカード文字を使用できます。アンダースコアは1つの文字を表します。パーセント記号(%)は0(ゼロ)個以上の文字を表します。
大/小文字が区別されます。例2-44に示すように、文字列'Johnson'はパターン'J%s_n'に一致しますが、'J%S_N'には一致しません。
例2-44 式でのLIKE演算子
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では、バックスラッシュをエスケープ文字として使用しているため、文字列内のパーセント記号はワイルドカードとしての役割は果たしません。
例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演算子は、指定された範囲に、ある値が含まれているかどうかをテストします。x BETWEEN a AND bは、(x>=a) AND (x<=b)と同じ値を戻します。
例2-46では、例2-35のprint_booleanプロシージャを起動し、BETWEEN演算子を含む式の値を出力します。
例2-46 式での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 = TRUE2 BETWEEN 1 AND 2 = TRUE2 BETWEEN 3 AND 4 = FALSE
|
関連項目: BETWEENの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
IN演算子は、セット・メンバーシップをテストします。x IN (set)は、xがsetのメンバーと等しい場合にのみTRUEを戻します。
例2-47では、例2-35のprint_booleanプロシージャを起動し、IN演算子を含む式の値を出力します。
例2-47 式での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は、setにNULL値が含まれている場合に発生する状況を示しています。(例2-48では、例2-35のprint_booleanプロシージャを起動します。)
例2-48 NULL値を含む集合でのIN演算子
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
|
関連項目: INの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
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式は、制御文(第4章「PL/SQLの制御文」を参照)およびDML文のWHERE句で条件として使用します。
BOOLEAN変数自体を条件として使用できますが、TRUE値またはFALSE値と比較する必要はありません。例2-49では、ループの条件は等価です。
ここでのトピック
この説明では、単純な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を戻します。
例2-50では、単純なCASE式の値を変数appraisalに代入します。selectorはgradeです。
例2-50 単純なCASE式
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に示すように、selectorの値がNULLの場合、WHEN NULLでは一致させることができません。かわりに、例2-53に示すように、検索CASE式をWHEN boolean_expression IS NULLとともに使用します。
例2-51 WHEN NULLを使用した単純なCASE式
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 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を戻します。
例2-52では、検索CASE文の値を変数appraisalに代入します。
例2-52 検索CASE式
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では、検索CASE式を使用して、例2-51の問題を解決します。
例2-53 WHEN ... IS NULLを使用した検索CASE式
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ファンクションを使用できます。
分析ファンクション(LAG、RATIO_TO_REPORTなど)
データ・マイニング・ファンクション(CLUSTER_ID、FEATURE_VALUEなど)
エンコーディング・ファンクションおよびデコーディング・ファンクション(DECODE、DUMPなど)
モデル・ファンクション(ITERATION_NUMBER、PREVIOUSなど)
オブジェクト参照ファンクション(REF、VALUEなど)
XMLファンクション(APPENDCHILDXML、EXISTSNODEなど)
次の変換ファンクション:
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ファンクションの有効な引数であるCHAR、VARCHAR2およびLONGの値と、最大16380バイトのLONG RAWおよびBLOBの値に対して実行可能です。
PL/SQLには、PL/SQL例外処理コードで使用するためのSQLCODEとSQLERRMの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の詳細は、「識別子」を参照してください。文字$はplsql_identifier内でも使用できますが、そこでは特別な意味を持ちません。
$IF
$THEN
$ELSE
$ELSIF
$ERROR
選択ディレクティブは、コンパイルするソース・テキストを選択します。
構文
$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が存在する場合は、そのテキストがコンパイルされますが、存在しない場合は、どのテキストもコンパイルされません。
選択ディレクティブの例は、「条件付きコンパイルの例」を参照してください。
エラー・ディレクティブは、コンパイル時にユーザー定義のエラー・メッセージを生成します。
構文
$ERROR varchar2_static_expression $END
次のコンパイル時のエラー・メッセージを生成します。stringはvarchar2_static_expressionの値です。
PLS-00179: $ERROR: string
varchar2_static_expressionの構文の詳細は、「静的なVARCHAR2式」を参照してください。
エラー・ディレクティブの使用例は、例2-58を参照してください。
構文
$$name
name(引用符で囲まれていないPL/SQL識別子)の詳細は、「識別子」を参照してください。
通常、問合せディレクティブは、選択ディレクティブのboolean_static_expressionで使用しますが、その型の変数またはリテラルを使用できるすべての場所で使用できます。また、通常のPL/SQLでは(変数ではなく)リテラルのみ使用可能な場所でも使用できます(たとえば、VARCHAR2変数のサイズを指定するために使用できます)。
ここでのトピック
現行のPL/SQLユニットでディレクティブが使用されるソース行の番号を値として持つPLS_INTEGERリテラル。選択ディレクティブの$$PLSQL_LINEの例を次に示します。
$IF $$PLSQL_LINE = 32 $THEN ...
現行のPL/SQLユニットの名前を持つVARCHAR2リテラル。現行のPL/SQLユニットが無名ブロックの場合、$$PLSQL_UNITの値はNULL値になります。選択ディレクティブの$$PLSQL_UNITの例を次に示します。
$IF $$PLSQL_UNIT IS NULL $THEN ...
選択ディレクティブには静的なBOOLEAN式が必要なため、次のようなVARCHAR2比較は使用できません。
$IF $$PLSQL_UNIT = 'AWARD_BONUS' $THEN ...
$$plsql_compilation_parameter
名前plsql_compilation_parameterは、PL/SQLコンパイル・パラメータ(PLSCOPE_SETTINGSなど)です。これらのパラメータの詳細は、表1-2を参照してください。
例2-54のSQL*Plusスクリプトでは、事前定義の問合せディレクティブ$$PLSQL_LINEおよび$$PLSQL_UNITをそれぞれ通常のPLS_INTEGERおよびVARCHAR2リテラルとして使用し、値がどのように代入されるかを示しています。
例2-54 事前定義の問合せディレクティブ$$PLSQL_LINEおよび$$PLSQL_UNIT
SQL> CREATE OR REPLACE PROCEDURE p
2 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 END;
11 /
Procedure created.
SQL> BEGIN
2 p;
3 DBMS_OUTPUT.PUT_LINE('Outside p');
4 DBMS_OUTPUT.PUT_LINE('$$PLSQL_UNIT = ' || $$PLSQL_UNIT);
5 END;
6 /
結果:
Inside p i = 6 $$PLSQL_LINE = 8 $$PLSQL_UNIT = P Outside p $$PLSQL_UNIT = PL/SQL procedure successfully completed.
例2-55では、PL/SQLコンパイル・パラメータの現在の値を表示します。
例2-55 PL/SQLのコンパイル・パラメータの値の表示
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 = $$PLSQL_CCFLAGS = 99 $$PLSQL_CODE_TYPE = INTERPRETED $$PLSQL_OPTIMIZE_LEVEL = 2 $$PLSQL_WARNINGS = ENABLE:ALL $$NLS_LENGTH_SEMANTICS = BYTE
|
注意: SQL*Plus環境では、SHOW PARAMETERSコマンドを使用して、PL/SQLコンパイル・パラメータを含む初期化パラメータの現在の値を表示できます。SHOWコマンドとPARAMETERSオプションの詳細は、『SQL*Plusユーザーズ・ガイドおよびリファレンス』を参照してください。 |
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言語リファレンス』を参照してください。
例2-56では、PLSQL_CCFLAGSを使用して、ユーザー定義の問合せディレクティブ$$Some_Flagに値を代入し、さらに、(推奨されてはいませんが)それ自体にも値を代入します。先に行った代入は後で行った代入によってオーバーライドされるため、$$Some_Flagの結果の値は2になり、PLSQL_CCFLAGSの結果の値はALTER SESSION文によって代入される値('Some_Flag:1, Some_Flag:2, PLSQL_CCFlags:99')ではなく、それ自体に代入される値(99)になります。
例2-56 PLSQL_CCFLAGSによるそれ自体への値の代入
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
|
注意: PLSQL_CCFLAGSのコンパイル時の値は、ストアドPL/SQLユニットのメタデータとともに格納されているため、ユニットを明示的に再コンパイルするときにその値を再利用できます。詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。 |
PLSQL_CCFLAGSの詳細は、『Oracle Databaseリファレンス』を参照してください。
問合せディレクティブ($$name)を解決できず(つまり、値を判断できず)、ソース・テキストがラップされていない場合は、PL/SQLにより警告PLW-6003が発行され、未解決の問合せディレクティブの値としてNULLが代入されます。ソース・テキストがラップされている場合は、未解決の問合せディレクティブが示されないように、警告メッセージが無効になります。PL/SQLソース・テキストのラップの詳細は、付録A「PL/SQLのソース・テキストのラップ」を参照してください。
静的な式は、値がコンパイル時に決定される式です。文字の比較、変数またはファンクションの起動は含まれていません。静的な式は、条件付きコンパイル・ディレクティブで使用できる唯一の式です。
静的な式は、コンパイル時に判断可能な値を持つ(つまり、変数またはファンクションへの参照が含まれていない)式です。静的な式は、条件付きコンパイル・ディレクティブで使用できる唯一の式です。
ここでのトピック
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
静的な式の詳細は、「静的な式」を参照してください。
最大サイズが32767バイトである文字列リテラル
リテラルの詳細は、「リテラル」を参照してください。
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式」を参照してください。
静的定数は、パッケージ仕様部で次の構文を使用して宣言します。
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でコンパイルされるコードは変更されません。
例2-57 静的定数
CREATE PACKAGE my_debug IS debug CONSTANT BOOLEAN := TRUE; trace CONSTANT BOOLEAN := TRUE; END my_debug; / CREATE PROCEDURE my_proc1 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 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パッケージでは、次の静的定数が提供されます。
VER_LE_v形式のBOOLEAN定数の値はそれぞれ、データベース・バージョンがv以下の場合にTRUEになり、それ以外の場合はFALSEになります。
VER_LE_v_r形式のBOOLEAN定数の値はそれぞれ、データベース・バージョンがv以下でリリースがr以下の場合にTRUEになり、それ以外の場合はFALSEになります。
Oracle Database 10g以下を表す定数はすべて値がFALSEになります。
DBMS_DB_VERSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
例2-58では、データベース・バージョンおよびリリースがOracle Database 10gリリース2より前の場合はエラー・メッセージを生成し、それ以外の場合は、バージョンおよびリリースがサポート対象であるというメッセージを表示してOracle Database 10gリリース2から使用可能になったCOMMIT文を使用します。
例2-58 データベース・バージョンを確認するコード
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 11.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の場合のみに一部のコードをコンパイルします。
例2-59 異なるデータベース・バージョンに対する異なるコードのコンパイル
ALTER SESSION SET PLSQL_CCFLAGS = 'my_debug:FALSE, my_tracing:FALSE'; CREATE OR REPLACE PACKAGE my_pkg 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) 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 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のコードの行は、空白行として表示されます。
条件付きコンパイル・ディレクティブは、(「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