この章では、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 THEN
DBMS_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 = TRUE
2 BETWEEN 1 AND 2 = TRUE
2 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