この章では、PL/SQL言語の次の点について説明します。
PL/SQLでは、識別子およびソース・コードに使用されるデータベース・キャラクタ・セット、および各国語データに使用される各国語キャラクタ・セットの2つのキャラクタ・セットがサポートされています。 このトピックの内容は、データベース・キャラクタ・セットにのみ適用されます。 各国語キャラクタ・セットについては、「NCHARおよびNVARCHAR2データ型」を参照してください。
PL/SQLプログラムは、次の文字を使用したテキストとして作成されます。
大文字と小文字の英字、AからZおよびaからz
数字、0から 9
記号、( ) + - * / < > = ! ~ ^ ; : . ' @ % , " # $ & _ | { } ? [ ]
タブ、空白および改行
PL/SQLキーワードは大/小文字が区別されないため、文字列リテラルと文字リテラルの中を除き、小文字の英字は対応する大文字の英字と等価です。
PL/SQLテキストの行には字句単位と呼ばれる文字のグループがあります。
デリミタ(単純記号とコンパウンド記号)
識別子(予約語を含む)
リテラル
コメント
隣接する識別子は、空白またはデリミタで区切る必要があります。 次に例を示します。
SQL> BEGIN 2 IF x > y THEN high := x; END IF; -- correct 3 IF x > y THEN high := x; ENDIF; -- incorrect 4 END; 5 / END; * ERROR at line 4: ORA-06550: line 4, column 4: PLS-00103: Encountered the symbol ";" when expecting one of the following: if SQL>
文字列リテラルとコメントの場合を除き、字句単位の中に空白を埋め込むことはできません。 次に例を示します。
SQL> BEGIN 2 count := count + 1; -- correct 3 count : = count + 1; -- incorrect 4 END; 5 / count : = count + 1; -- incorrect * ERROR at line 3: ORA-06550: line 3, column 9: PLS-00103: Encountered the symbol ":" when expecting one of the following: := . ( @ % ; SQL>
構造を示すために、改行で行を分けたり、空白またはタブで行にインデントを付けることができます。 次に例を示します。
SQL> DECLARE 2 x NUMBER := 10; 3 y NUMBER := 5; 4 max NUMBER; 5 BEGIN 6 IF x>y THEN max:=x;ELSE max:=y;END IF; -- correct but hard to read 7 8 -- Easier to read: 9 10 IF x > y THEN 11 max:=x; 12 ELSE 13 max:=y; 14 END IF; 15 END; 16 / PL/SQL procedure successfully completed. SQL>
ここでのトピック:
デリミタは、PL/SQLにとって特別な意味を持つ単純記号またはコンパウンド記号です。 表2-1に、PL/SQLのデリミタを示します。
表2-1 PL/SQLのデリミタ
| 記号 | 意味 |
|---|---|
|
|
加算演算子 |
|
|
属性のインジケータ |
|
|
文字列のデリミタ |
|
|
構成要素の選択子 |
|
|
除算演算子 |
|
|
式またはリストのデリミタ |
|
|
式またはリストのデリミタ |
|
|
ホスト変数のインジケータ |
|
|
項目のセパレータ |
|
|
乗算演算子 |
|
|
二重引用符で囲んだ識別子のデリミタ |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
リモート・アクセスのインジケータ |
|
|
文の終了記号 |
|
|
減算/否定演算子 |
|
|
代入演算子 |
|
|
結合演算子 |
|
|
連結演算子 |
|
|
指数演算子 |
|
|
ラベルのデリミタ(開始) |
|
|
ラベルのデリミタ(終了) |
|
|
複数行コメントのデリミタ(開始) |
|
|
複数行コメントのデリミタ(終了) |
|
|
範囲演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
関係演算子 |
|
|
単一行コメントのインジケータ |
識別子を使用して、定数、変数、例外、カーソル、カーソル変数、サブプログラム、パッケージなどのPL/SQLプログラムに名前を付けることができます。
識別子の最小長は1文字、最大長は30文字です。 最初の文字は英字である必要がありますが、2文字目以降は英字、数字、ドル記号($)、アンダースコア(_)およびシャープ記号(#)のいずれでもかまいません。 たとえば、次の識別子を使用できます。
X t2 phone# credit_limit LastName oracle$number money$$$tree SN## try_again_
前述の文字以外は、識別子に使用できません。 たとえば、次の識別子は使用できません。
mine&yours -- ampersand (&) is not allowed debit-amount -- hyphen (-) is not allowed on/off -- slash (/) is not allowed user id -- space is not allowed
PL/SQLは、識別子の大/小文字を区別しません。 たとえば、PL/SQLは次の識別子を同じものとみなします。
lastname LastName LASTNAME
英字かどうかに関係なく、すべての文字が重要となります。 たとえば、PL/SQLは、次の2つの識別子を別のものとして扱います。
lastname last_name
識別子はあいまいなものではなく、意味のあるものにします。 たとえば、cost_per_thousandは意味が明白ですが、cptは意味があいまいです。
ここでのトピック:
予約語とキーワードには、いずれもPL/SQLに対して特別な意味があります。 予約語とキーワードの違いとして、予約語は識別子として使用できないという点があげられます。 キーワードは識別子として使用できますが、お薦めしません。
予約語を再定義しようとするとコンパイル・エラーが発生します。 次に例を示します。
SQL> DECLARE 2 end BOOLEAN; 3 BEGIN 4 NULL; 5 END; 6 / end BOOLEAN; * ERROR at line 2: ORA-06550: line 2, column 3: PLS-00103: Encountered the symbol "END" when expecting one of the following: begin function pragma procedure subtype type <an identifier> <a double-quoted delimited-identifier> current cursor delete exists prior The symbol "begin was inserted before "END" to continue. ORA-06550: line 5, column 4: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted SQL>
表D-1に、PL/SQLの予約語を示します。
キーワードもPL/SQLに対して特別な意味がありますが、キーワードは再定義することができます(ただし、推奨されていません)。 表D-2に、PL/SQLのキーワードを示します。
例外INVALID_NUMBERなど、パッケージSTANDARDでグローバルに宣言されている識別子は、再宣言できます。 ただし、事前定義の識別子を再宣言すると、ローカルな宣言がグローバルな宣言をオーバーライドするためエラーが発生しやすくなります。
柔軟性を高めるために、PL/SQLでは識別子を二重引用符で囲むことができます。 通常は、このようにする必要はありませんが、ときには便利な場合もあります。 二重引用符で囲んだ識別子には、空白など、二重引用符を除くすべての印字可能文字を任意に並べて入れることができます。 したがって、次の識別子は有効です。
"X+Y" "last name" "on/off switch" "employee(s)" "*** header info ***"
二重引用符で囲んだ識別子の最大サイズは、二重引用符を数えずに30字です。 PL/SQLの予約語を二重引用符で囲んだ識別子として使用することもできますが、それは好ましくないプログラミング習慣です。
リテラルは、識別子によって表現する必要がない明示的な数値、文字、文字列またはブール値です。 例として、数値リテラル147やブール・リテラルFALSEがあり PL/SQLのデータ型の詳細は、「事前定義のPL/SQLのスカラー・データ型およびサブタイプ」を参照してください。
ここでのトピック:
算術式では、整数と実数の2種類の数値リテラルを使用できます。 整数リテラルは、小数点を持たず、必要に応じて符号を付けた整数です。 次に例を示します。
030 6 -14 0 +32767
実数リテラルとは、小数点を持ち、必要に応じて符号を付けた整数または小数です。 次に例を示します。
6.6667 0.0 -12.0 3.14159 +8300.00 .5 25.
PL/SQLでは、12.0や25.などの数字は、整数値がある場合でも実数とみなします。
数字のみで構成される-2147483648から2147483647の範囲の数値リテラルの値は、PLS_INTEGERデータ型です。それ以外の数値リテラルは、NUMBERデータ型です。 数値のみで構成されているリテラル値の後にfまたはdを追加して、それぞれBINARY_FLOATまたはBINARY_TABLEを指定できます。 データ型のプロパティは、「事前定義のPL/SQL数値データ型およびサブタイプ」を参照してください。
数値リテラルはドル記号やカンマを含むことはできませんが、科学表記法で書くことができます。 数字の後にE(またはe)を付けて、必要な場合は符号付き整数を続けます。 次に例を示します。
2E5 1.0E-7 3.14159e0 -1E38 -9.5e-3
xEyは、xに10のy乗を掛けることを意味します。 次の例で示すように、Eの前の数に、Eの後の数の10の累乗を掛けます(二重アスタリスク(**)は指数演算子です)。
5E3 = 5 * 10**3 = 5 * 1000 = 5000
Eの後の数値は、小数点が移動する桁数にも対応しています。 上の例では、暗黙的な小数点が3桁右に移動しました。 次の例では、3桁左に移動します。
5E-3 = 5 * 10**-3 = 5 * 0.001 = 0.005
NUMBERリテラルの絶対値は、1.0E-130から1.0E126(ただし、1.0E126を含まない)の範囲にすることができます。 リテラルは、0の場合もあります。有効範囲外の結果の詳細は、「NUMBERデータ型」を参照してください。
例2-1 NUMBERリテラル
SQL> DECLARE 2 n NUMBER; 3 BEGIN 4 n := -9.999999E-130; 5 n := 9.999E125; 6 n := 10.0E125; 7 END; 8 / n := 10.0E125; * ERROR at line 6: ORA-06550: line 6, column 8: PLS-00569: numeric overflow or underflow ORA-06550: line 6, column 3: PL/SQL: Statement ignored SQL>
例2-2に示すように、実数リテラルには、後ろにfまたはd文字を付けて、BINARY_FLOATまたはBINARY_DOUBLE型を指定できます。
文字リテラルは引用符(')で囲まれた1文字のことです。 文字リテラルには、PL/SQLキャラクタ・セットのすべての印刷可能文字(英字、数字、空白および特殊記号)を使用できます。 次に例を示します。
'Z' '%' '7' ' ' 'z' '('
文字リテラルの中で、PL/SQLは大/小文字を区別します。 このため、PL/SQLはリテラル'Z'と'z'を違うものとして扱います。 また文字リテラル'0'から'9'は、整数リテラルと同じではありませんが、暗黙のうちに整数に変換されるため、算術式の中で使用できます。
文字値は、識別子によって表現することも、引用符(')で囲まれた0(ゼロ)文字以上の並びである文字列リテラルとして明示的に書くこともできます。 NULL文字列('')を除くすべての文字列リテラルは、CHARデータ型に属します。 次に例を示します。
'Hello, world!' 'XYZ Corporation' '10-NOV-91' 'He said "Life is like licking honey from a thorn."' '$1,000,000'
文字列リテラルの中で、PL/SQLは大/小文字を区別します。 たとえば、PL/SQLは次の2つのリテラルを異なるものとして扱います。
'baker' 'Baker'
文字列の中でアポストロフィを表現する場合は、引用符を2つ書きます。これは二重引用符を書く場合とは違う意味を持ちます。
'I''m a string, you''re a string.'
次の表記法を使用して、リテラルに独自のデリミタ文字を定義することもできます。 デリミタ文字には、文字列に含まれていない文字を使用します。これによって、リテラル内の引用符をエスケープする必要がなくなります。
-- q'!...!' notation allows use of single quotes inside literal string_var := q'!I'm a string, you're a string.!';
デリミタ[、{、<、(を]、}、>、)とペアで使用すると、'INVALID'の前後の引用符を二重にすることなく、SQL文を表す文字列リテラルをサブプログラムに渡すことができます。
func_call(q'[SELECT index_name FROM user_indexes WHERE status ='INVALID']');
NCHARリテラルおよびNVARCHAR2リテラルの前には、次の例のように、qではなくnqを付けます。この場合、00E0は文字éを表します。
where_clause := nq'#WHERE COL_VALUE LIKE '%\00E9'#';
NCHARデータ型およびUnicode文字列の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
ブール・リテラルとは、事前定義の値TRUE、FALSEおよびNULLのことです。 NULLは、存在しない値、不明な値または適用できない値を示します。 ブール・リテラルは値であり、文字列ではないことに注意してください。 たとえば、TRUEは数値25と同じように1つの値です。
例2-3に示すように、日時リテラルには、データ型に応じて様々な形式があります。
例2-3 日時リテラルの使用
SQL> DECLARE 2 d1 DATE := DATE '1998-12-25'; 3 t1 TIMESTAMP := TIMESTAMP '1997-10-22 13:01:01'; 4 5 t2 TIMESTAMP WITH TIME ZONE := 6 TIMESTAMP '1997-01-31 09:26:56.66 +02:00'; 7 8 -- Three years and two months 9 -- For greater precision, use the day-to-second interval 10 11 i1 INTERVAL YEAR TO MONTH := INTERVAL '3-2' YEAR TO MONTH; 12 13 -- Five days, four hours, three minutes, two and 1/100 seconds 14 15 i2 INTERVAL DAY TO SECOND := 16 INTERVAL '5 04:03:02.01' DAY TO SECOND; 17 18 BEGIN 19 NULL; 20 END; 21 / PL/SQL procedure successfully completed. SQL>
|
参照:
|
PL/SQLコンパイラは、コメントを無視します。 プログラムにコメントを付け加えると、わかりやすくなり理解に役立ちます。 一般に、コメントは各コード・セグメントの目的や使用方法を説明するために使用します。 また、廃止されたコード部分や作成途中のコード部分をコメントに入れて無効化することもできます。
ここでのトピック:
単一行コメントは、--で始まります。 例2-4に示すように、行の中の任意の場所に置くことができ、その行の終わりまで続きます。
例2-4 単一行コメント
SQL> DECLARE 2 howmany NUMBER; 3 num_tables NUMBER; 4 BEGIN 5 -- Begin processing 6 SELECT COUNT(*) INTO howmany 7 FROM USER_OBJECTS 8 WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables 9 num_tables := howmany; -- Compute some other value 10 END; 11 / PL/SQL procedure successfully completed. SQL>
プログラムのテストまたはデバッグ中に、コード内の1行をコメントにすることによって無効にできます。 次に例を示します。
-- DELETE FROM employees WHERE comm_pct IS NULL
例2-5に示すように、複数行コメントは、/*で始まって*/で終わり、複数行にまたがることができます。 複数行コメントのデリミタを使用すると、コードの一部分をコメントにできます。
例2-5 複数行コメント
SQL> DECLARE 2 some_condition BOOLEAN; 3 pi NUMBER := 3.1415926; 4 radius NUMBER := 15; 5 area NUMBER; 6 BEGIN 7 /* Perform some simple tests and assignments */ 8 IF 2 + 2 = 4 THEN 9 some_condition := TRUE; 10 /* We expect this THEN to always be performed */ 11 END IF; 12 /* The following line computes the area of a circle using pi, 13 which is the ratio between the circumference and diameter. 14 After the area is computed, the result is displayed. */ 15 area := pi * radius**2; 16 DBMS_OUTPUT.PUT_LINE('The area is: ' || TO_CHAR(area)); 17 END; 18 / The area is: 706.858335 PL/SQL procedure successfully completed. SQL>
プログラムは、変数と定数に値を格納します。 プログラムの実行中に、変数の値を変更できますが、定数の値は変更できません。
変数および定数は、任意のPL/SQLブロック、サブプログラムまたはパッケージの宣言部で宣言できます。 宣言によって、値の記憶域を割り当て、データ型を指定し、値を参照できるように格納場所の名前を決めます。
ここでのトピック:
例2-6では、DATE型の変数、(初期値0が代入される)SMALLINT型の変数および3つのREAL型の変数を宣言しています。 代入演算子の後に続く式は複雑なものでもかまいません。また、area変数の宣言の場合と同様に、事前に初期化されている変数を参照することもできます。
変数は、ブロックまたはサブプログラムに入るたびに初期化されます。 デフォルトでは、変数はNULLに初期化されます。
定数を宣言するには、型指定子の前にキーワードCONSTANTが必要です。 次の宣言では、REAL型の定数の名前を決め、定数に変更不可能な値5000を代入しています。 定数は、宣言の中で初期化する必要があります。 定数は、ブロックまたはサブプログラムに入るたびに初期化されます。
変数の初期化には、代入演算子のかわりにキーワードDEFAULTも使用できます。 DEFAULTを使用して、サブプログラム・パラメータ、カーソル・パラメータおよびユーザー定義レコードのフィールドを初期化することもできます。
標準的な値を持つ変数には、DEFAULTを使用します。 特殊な値を持つ変数(カウンタやアキュムレータ)には、代入演算子を使用します。
宣言でNOT NULL制約を指定し、変数にNULL値を代入できないようにすることができます。 変数はデフォルトでNULLに初期化されるため、NOT NULLを指定する宣言でもデフォルト値を指定する必要があります。
PL/SQLサブタイプNATURALN、POSITIVENおよびSIMPLE_INTEGERは、NOT NULLと同様に事前定義されています。 これらのサブタイプのいずれかの変数を宣言する場合、NOT NULL制約は省略できますが、デフォルト値は指定する必要があります。
%TYPE属性を使用すると、事前に宣言されている変数、フィールド、レコード、ネストした表またはデータベース列と同じデータ型の定数、変数、フィールドまたはパラメータを宣言できます。 参照先項目が変更されると、宣言は自動的に更新されます。 これによって、たとえば、VARCHAR2列を長くする場合にコードを変更する必要がなくなります。
%TYPEを使用して宣言された項目(参照元項目)は、常に、参照先項目のデータ型を継承します。 参照元項目は、参照先項目がデータベース列ではない場合にのみ、制約を継承します。 参照元項目は、データベース列ではなく、NOT NULL制約を持たない場合にのみ、デフォルト値を継承します。
例2-10では、変数debitは、変数creditのデータ型を継承しています。 変数upper_name、lower_nameおよびinit_nameは、変数nameのデータ型およびデフォルト値を継承しています。
例2-10 %TYPEを使用したその他の変数の型の変数の宣言
SQL> DECLARE 2 credit PLS_INTEGER RANGE 1000..25000; 3 debit credit%TYPE; -- inherits data type 4 5 name VARCHAR2(20) := 'JoHn SmItH'; 6 upper_name name%TYPE; -- inherits data type and default value 7 lower_name name%TYPE; -- inherits data type and default value 8 init_name name%TYPE; -- inherits data type and default value 9 BEGIN 10 DBMS_OUTPUT.PUT_LINE ('name: ' || name); 11 DBMS_OUTPUT.PUT_LINE ('upper_name: ' || UPPER(name)); 12 DBMS_OUTPUT.PUT_LINE ('lower_name: ' || LOWER(name)); 13 DBMS_OUTPUT.PUT_LINE ('init_name: ' || INITCAP(name)); 14 END; 15 / name: JoHn SmItH upper_name: JOHN SMITH lower_name: john smith init_name: John Smith PL/SQL procedure successfully completed. SQL>
例2-10の変数nameにNOT NULL制約を追加し、この変数を参照する別の変数を宣言する場合は、例2-11に示すように、新しい項目にデフォルト値を指定する必要があります。
例2-11 NOT NULL参照型での%TYPEの不適切な使用
SQL> DECLARE 2 name VARCHAR2(20) NOT NULL := 'JoHn SmItH'; 3 same_name name%TYPE; 4 BEGIN 5 NULL; 6 END; 7 / same_name name%TYPE; * ERROR at line 3: ORA-06550: line 3, column 15: PLS-00218: a variable declared NOT NULL must have an initialization assignment SQL>
例2-12では、変数upper_name、lower_nameおよびinit_nameは、変数nameのデータ型およびNOT NULL制約を継承していますが、デフォルト値は継承していません。 例2-11に示すエラーを回避するには、これらに独自のデフォルト値を代入します。
例2-12 NOT NULL参照型での%TYPEの適切な使用
SQL> DECLARE 2 name VARCHAR2(20) NOT NULL := 'JoHn SmItH'; 3 upper_name name%TYPE := UPPER(name); 4 lower_name name%TYPE := LOWER(name); 5 init_name name%TYPE := INITCAP(name); 6 BEGIN 7 DBMS_OUTPUT.PUT_LINE('name: ' || name); 8 DBMS_OUTPUT.PUT_LINE('upper_name: ' || upper_name); 9 DBMS_OUTPUT.PUT_LINE('lower_name: ' || lower_name); 10 DBMS_OUTPUT.PUT_LINE('init_name: ' || init_name); 11 END; 12 / name: JoHn SmItH upper_name: JOHN SMITH lower_name: john smith init_name: John Smith PL/SQL procedure successfully completed. SQL>
%TYPE属性は、データベース列を参照する変数を宣言する場合に特に便利です。 table_name.column_name.%TYPEを使用してデータ項目を宣言する場合、参照されるデータ型または属性(精度、位取りおよび長さなど)を知っておく必要はありません。また、これらが変更された場合でも、コードを更新する必要はありません。
例2-13では、参照元項目が、列制約またはデフォルト値をデータベース列から継承していないことを示しています。
例2-13 %TYPEを使用した表の列の型の変数の宣言
SQL> CREATE TABLE employees_temp ( 2 empid NUMBER(6) NOT NULL PRIMARY KEY, 3 deptid NUMBER(6) CONSTRAINT c_employees_temp_deptid 4 CHECK (deptid BETWEEN 100 AND 200), 5 deptname VARCHAR2(30) DEFAULT 'Sales' 6 ); Table created. SQL> SQL> DECLARE 2 v_empid employees_temp.empid%TYPE; 3 v_deptid employees_temp.deptid%TYPE; 4 v_deptname employees_temp.deptname%TYPE; 5 BEGIN 6 v_empid := NULL; -- Null constraint not inherited 7 v_deptid := 50; -- Check constraint not inherited 8 DBMS_OUTPUT.PUT_LINE 9 ('v_deptname: ' || v_deptname); -- Default value not inherited 10 END; 11 / v_deptname: PL/SQL procedure successfully completed. SQL>
|
参照:
|
%ROWTYPE属性を使用すると、表またはビュー内の行を表すレコード型を宣言できます。 参照される表またはビュー内の各列に対して、同じ名前およびデータ型のフィールドがレコードにあります。 レコード内のフィールドを参照するには、record_name.field_nameを使用します。 例2-14に示すように、このレコードのフィールドは、対応する列の制約またはデフォルト値を継承しません。
参照先項目の表またはビューが変更されると、宣言は自動的に更新されます。 列が表またはビューに追加されたり、表またはビューから削除された場合などに、コードを変更する必要はありません。
例2-14 %ROWTYPEを使用した、表の行を表すレコードの宣言
SQL> CREATE TABLE employees_temp ( 2 empid NUMBER(6) NOT NULL PRIMARY KEY, 3 deptid NUMBER(6) CONSTRAINT c_employees_temp_deptid 4 CHECK (deptid BETWEEN 100 AND 200), 5 deptname VARCHAR2(30) DEFAULT 'Sales' 6 ); Table created. SQL> SQL> DECLARE 2 emprec employees_temp%ROWTYPE; 3 BEGIN 4 emprec.empid := NULL; -- Null constraint not inherited 5 emprec.deptid := 50; -- Check constraint not inherited 6 DBMS_OUTPUT.PUT_LINE 7 ('emprec.deptname: ' || emprec.deptname); 8 -- Default value not inherited 9 END; 10 / emprec.deptname: PL/SQL procedure successfully completed. SQL>
例2-14のレコードemprecには、表employees_tempのすべての列に対するフィールドがあります。 例2-15のレコードdept_recには、表departmentsの列のサブセットに対する列があります。
例2-15 表の列のサブセットを表すレコードの宣言
SQL> DECLARE
2 CURSOR c1 IS
3 SELECT department_id, department_name
4 FROM departments;
5
6 dept_rec c1%ROWTYPE; -- includes subset of columns in table
7
8 BEGIN
9 NULL;
10 END;
11 /
PL/SQL procedure successfully completed.
SQL>
例2-15のレコードjoin_recには、2つの表employeesおよびdepartmentsからの列があります。
例2-16 結合からの列を表すレコードの宣言
SQL> DECLARE
2 CURSOR c2 IS
3 SELECT employee_id, email, employees.manager_id, location_id
4 FROM employees, departments
5 WHERE employees.department_id = departments.department_id;
6
7 join_rec c2%ROWTYPE; -- includes columns from two tables
8
9 BEGIN
10 NULL;
11 END;
12 /
PL/SQL procedure successfully completed.
SQL>
ここでのトピック:
%ROWTYPE宣言に初期化句を含めることはできませんが、レコード中のすべてのフィールドに一度に値を代入する方法が2つあります。
レコードの宣言で同じ表またはカーソルが参照されている場合は、例2-17に示すように、あるレコードを別のレコードに代入できます。
SELECT文またはFETCH文を使用すると、レコードに列値のリストを代入できます。
列名の順番は、参照される表またはビューを作成したCREATE TABLE文またはCREATE VIEW文で定義された順番である必要があります。 レコード型のコンストラクタが存在しない場合は、代入文を使用して列の値のリストをレコードに代入できません。
例2-17 あるレコードの別のレコードへの正しい代入および間違った代入
SQL> DECLARE 2 dept_rec1 departments%ROWTYPE; 3 dept_rec2 departments%ROWTYPE; 4 5 CURSOR c1 IS SELECT department_id, location_id 6 FROM departments; 7 8 dept_rec3 c1%ROWTYPE; 9 dept_rec4 c1%ROWTYPE; 10 11 BEGIN 12 dept_rec1 := dept_rec2; -- declarations refer to same table 13 dept_rec3 := dept_rec4; -- declarations refer to same cursor 14 dept_rec2 := dept_rec3; 15 END; 16 / dept_rec2 := dept_rec3; * ERROR at line 14: ORA-06550: line 14, column 16: PLS-00382: expression is of wrong type ORA-06550: line 14, column 3: PL/SQL: Statement ignored SQL>
例2-18では、SELECT INTO文を使用して、レコードに列値のリストを代入しています。
%ROWTYPEに関連付けられたカーソルからフェッチされた選択リストは、単純名を持つ必要があります。また、選択項目が式の場合は、例2-19のcomplete_nameのように別名を持つ必要があります。
例2-19 %ROWTYPEに関連付けられた式の別名の使用
SQL> BEGIN 2 FOR item IN 3 (SELECT (first_name || ' ' || last_name) complete_name 4 FROM employees 5 WHERE ROWNUM < 11 6 ) LOOP 7 DBMS_OUTPUT.PUT_LINE 8 ('Employee name: ' || item.complete_name); 9 END LOOP; 10 END; 11 / Employee name: Ellen Abel Employee name: Sundar Ande Employee name: Mozhe Atkinson Employee name: David Austin Employee name: Hermann Baer Employee name: Shelli Baida Employee name: Amit Banda Employee name: Elizabeth Bates Employee name: Sarah Bell Employee name: David Bernstein PL/SQL procedure successfully completed. SQL>
PL/SQLでは前方参照ができません。 宣言文などの他の文で変数または定数を参照するときは、事前に宣言する必要があります。
PL/SQLではサブプログラムの前方宣言が可能です。 詳細は、「相互に起動し合うネストしたサブプログラムの作成」を参照してください。
言語によっては、同一のデータ型の複数の変数の並びを一度に宣言できます。 ただし、PL/SQLではそれができません。 各変数を別々に宣言する必要があります。 領域を節約するために、1行に複数の宣言を含めることができます。 次に例を示します。
SQL> DECLARE 2 i, j, k, l SMALLINT; 3 BEGIN 4 NULL; 5 END; 6 / i, j, k, l SMALLINT; * ERROR at line 2: ORA-06550: line 2, column 4: PLS-00103: Encountered the symbol "," when expecting one of the following: constant exception <an identifier> <a double-quoted delimited-identifier> table long double ref char time timestamp interval date binary national character nchar ORA-06550: line 2, column 14: PLS-00103: Encountered the symbol "SMALLINT" when expecting one of the following: . ( ) , * @ % & = - + < / > at in is mod remainder not rem => <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between || ORA-06550: line 5, column 4: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted SQL> DECLARE 2 i SMALLINT; j SMALLINT; k SMALLINT; l SMALLINT; 3 BEGIN 4 NULL; 5 END; 6 / PL/SQL procedure successfully completed. SQL>
PL/SQLの定数、変数、カーソル、カーソル変数、例外、プロシージャ、ファンクション、パッケージには、同じネーミング規則が適用されます。 名前には単純名、修飾名、リモート名または修飾リモート名があります。 次に例を示します。
単純名: プロシージャ名のみ。
raise_salary(employee_id, amount);
修飾名: プロシージャ名の前にそのプロシージャが含まれているパッケージの名前が付きます(この表記は、ドットによってパッケージ名とプロシージャ名が区切られるため、ドット表記法と呼ばれます)。
emp_actions.raise_salary(employee_id, amount);
リモート名: プロシージャ名の後にリモート・アクセスのインジケータ(@)とそのプロシージャが格納されているデータベースへのリンクが続きます。
raise_salary@newyork(employee_id, amount);
修飾名およびリモート名:
emp_actions.raise_salary@newyork(employee_id, amount);
ここでのトピック:
同じ有効範囲内では、宣言されたすべての識別子が一意である必要があります。 データ型が異なる場合でも、変数とパラメータは同じ名前を共有できません。 例2-20に示すように、重複する識別子が参照された場合は、エラーが発生します。
例2-20 同じ有効範囲での重複する識別子
SQL> DECLARE 2 id BOOLEAN; 3 id VARCHAR2(5); -- duplicate identifier 4 BEGIN 5 id := FALSE; 6 END; 7 / 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 SQL>
識別子に適用される有効範囲規則については、「PL/SQLの識別子の有効範囲と可視性」を参照してください。
例2-21に示すように、定数、変数およびパラメータの名前では、すべての識別子と同様に大/小文字が区別されません。
例2-21 識別子の大/小文字の区別なし
SQL> DECLARE 2 zip_code INTEGER; 3 Zip_Code INTEGER; 4 BEGIN 5 zip_code := 90120; 6 END; 7 / zip_code := 90120; * ERROR at line 5: ORA-06550: line 5, column 3: PLS-00371: at most one declaration for 'ZIP_CODE' is permitted ORA-06550: line 5, column 3: PL/SQL: Statement ignored SQL>
あいまいなSQL文では、データベース列の名前はローカル変数名および仮パラメータ名より優先されます。 たとえば、同じ名前の変数と列が1つのWHERE句で使用された場合、SQLは両方とも列を参照するとみなします。
例2-22 名前解決でのブロック・ラベルの使用
SQL> CREATE TABLE employees2 AS 2 SELECT last_name FROM employees; Table created. SQL> SQL> -- Deletes everyone, because both LAST_NAMEs refer to the column: SQL> SQL> BEGIN 2 DELETE FROM employees2 3 WHERE last_name = last_name; 4 DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); 5 END; 6 / Deleted 107 rows. PL/SQL procedure successfully completed. SQL> ROLLBACK; Rollback complete. SQL> SQL> -- Avoid error by giving column and variable different names: SQL> SQL> DECLARE 2 last_name VARCHAR2(10) := 'King'; 3 v_last_name VARCHAR2(10) := 'King'; 4 BEGIN 5 DELETE FROM employees2 6 WHERE last_name = v_last_name; 7 DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); 8 END; 9 / Deleted 2 rows. PL/SQL procedure successfully completed. SQL> ROLLBACK; Rollback complete. SQL> SQL> -- Avoid error by qualifying variable with block name: SQL> SQL> <<main>> -- Label block for future reference 2 DECLARE 3 last_name VARCHAR2(10) := 'King'; 4 v_last_name VARCHAR2(10) := 'King'; 5 BEGIN 6 DELETE FROM employees2 7 WHERE last_name = main.last_name; 8 DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); 9 END; 10 / Deleted 2 rows. PL/SQL procedure successfully completed. SQL> ROLLBACK; Rollback complete. SQL>
例2-23に示すように、ローカル変数と仮パラメータへの参照を、サブプログラム名を使用して修飾できます。
例2-23 名前解決でのサブプログラムの使用
SQL> DECLARE 2 FUNCTION dept_name (department_id IN NUMBER) 3 RETURN departments.department_name%TYPE 4 IS 5 department_name departments.department_name%TYPE; 6 BEGIN 7 SELECT department_name INTO dept_name.department_name 8 -- ^column ^local variable 9 FROM departments 10 WHERE department_id = dept_name.department_id; 11 -- ^column ^formal parameter 12 RETURN department_name; 13 END; 14 BEGIN 15 FOR item IN (SELECT department_id FROM departments) 16 LOOP 17 DBMS_OUTPUT.PUT_LINE 18 ('Department: ' || dept_name(item.department_id)); 19 END LOOP; 20 END; 21 / Department: Administration Department: Marketing Department: Purchasing Department: Human Resources Department: Shipping Department: IT Department: Public Relations Department: Sales Department: Executive Department: Finance Department: Accounting Department: Treasury Department: Corporate Tax Department: Control And Credit Department: Shareholder Services Department: Benefits Department: Manufacturing Department: Construction Department: Contracting Department: Operations Department: IT Support Department: NOC Department: IT Helpdesk Department: Government Sales Department: Retail Sales Department: Recruiting Department: Payroll PL/SQL procedure successfully completed. SQL>
SQL文CREATE SYNONYMを使用してシノニムを作成し、リモート・スキーマ・オブジェクトに関する位置の透過性を提供できます。 PL/SQLのサブプログラムまたはパッケージ内で宣言された項目に対してシノニムは作成できません。
|
参照: SQLのCREATE SYNONYM文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
識別子に対する参照は、その有効範囲と可視性に従って解決されます。 識別子の有効範囲とは、その識別子の参照が可能な、PL/SQLユニットの領域です。 識別子の可視性とは、修飾なしでその識別子の参照が可能な、PL/SQLユニットの領域です。
あるPL/SQLユニットで宣言された識別子は、そのユニットに対してはローカルであり、そのサブユニットに対してはグローバルです。 サブユニットでグローバル識別子が再宣言されると、そのサブユニット内では両方の識別子が有効範囲内にあることになりますが、ローカル識別子のみが表示されます。 グローバル識別子を参照するには、サブユニットでグローバル識別子を修飾する必要があります。
同じPL/SQLユニットで識別子を2回宣言することはできませんが、同じ識別子を2つの異なるユニットで宣言することはできます。 識別子が表す2つの項目は区別され、一方を変更しても他方には影響がありません。
PL/SQLユニットは、あるユニットから同じレベルの他のユニットで宣言されている識別子への参照はできません。そのような識別子は、そのブロックに対してローカルでもグローバルでもないためです。
例2-24に、いくつかのグローバル識別子とローカル識別子の有効範囲と可視性を示します。 グローバル識別子aは、最初のブロックで再宣言されています。
例2-24 識別子の有効範囲と可視性
SQL> DECLARE 2 a CHAR; -- Scope of a (CHAR) begins 3 b REAL; -- Scope of b begins 4 BEGIN 5 -- Visible: a (CHAR), b 6 7 DECLARE 8 a INTEGER; -- Scope of a (INTEGER) begins 9 c REAL; -- Scope of c begins 10 BEGIN 11 -- Visible: a (INTEGER), b, c 12 NULL; 13 END; -- Scopes of a (INTEGER) and c end 14 15 DECLARE 16 d REAL; -- Scope of d begins 17 BEGIN 18 -- Visible: a (CHAR), b, d 19 NULL; 20 END; -- Scope of d ends 21 22 -- Visible: a (CHAR), b 23 END; -- Scopes of a (CHAR) and b end 24 / PL/SQL procedure successfully completed. SQL>
例2-25では、変数birthdateをラベル付きのブロックouterで宣言し、サブブロックで再宣言した後、ブロック・ラベルで名前を修飾することによってサブブロック内で参照しています。
例2-25 ブロック・ラベルによる、再宣言されたグローバル識別子の修飾
SQL> <<outer>> 2 DECLARE 3 birthdate DATE := '09-AUG-70'; 4 BEGIN 5 DECLARE 6 birthdate DATE; 7 BEGIN 8 birthdate := '29-SEP-70'; 9 10 IF birthdate = outer.birthdate THEN 11 DBMS_OUTPUT.PUT_LINE ('Same Birthday'); 12 ELSE 13 DBMS_OUTPUT.PUT_LINE ('Different Birthday'); 14 END IF; 15 END; 16 END; 17 / Different Birthday PL/SQL procedure successfully completed. SQL>
例2-26では、変数ratingをプロシージャcheck_creditで宣言し、プロシージャ内のファンクションで再宣言した後、プロシージャ名で名前を修飾することによってファンクション内で参照しています。 (SQLの組込みファンクションTO_CHARは、引数に相当する文字を戻します。 TO_CHARの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)
例2-26 サブプログラム名による識別子の修飾
SQL> CREATE OR REPLACE PROCEDURE check_credit (limit NUMBER) AS 2 rating NUMBER := 3; 3 4 FUNCTION check_rating RETURN BOOLEAN IS 5 rating NUMBER := 1; 6 over_limit BOOLEAN; 7 BEGIN 8 IF check_credit.rating <= limit THEN 9 over_limit := FALSE; 10 ELSE 11 over_limit := TRUE; 12 rating := limit; 13 END IF; 14 RETURN over_limit; 15 END check_rating; 16 BEGIN 17 IF check_rating THEN 18 DBMS_OUTPUT.PUT_LINE 19 ('Credit rating over limit (' || TO_CHAR(limit) || '). ' 20 || 'Rating: ' || TO_CHAR(rating)); 21 ELSE 22 DBMS_OUTPUT.PUT_LINE 23 ('Credit rating OK. ' || 'Rating: ' || TO_CHAR(rating)); 24 END IF; 25 END; 26 / Procedure created. SQL> BEGIN 2 check_credit(1); 3 END; 4 / Credit rating over limit (1). Rating: 3 PL/SQL procedure successfully completed. SQL>
同じ有効範囲内では、混乱や予期しない結果を回避するためにラベルとサブプログラムに一意の名前を付けます。
例2-27では、ブロックおよびサブプログラムの両方にechoという名前を付けています。 ブロックおよびサブプログラムの両方で、xという変数を宣言しています。 サブプログラム内では、echo.xは、グローバル変数xではなく、ローカル変数xを参照します。
例2-27 同じ有効範囲内で同じ名前を持つラベルとサブプログラム
SQL> <<echo>>
2 DECLARE
3 x NUMBER := 5;
4
5 PROCEDURE echo AS
6 x NUMBER := 0;
7 BEGIN
8 DBMS_OUTPUT.PUT_LINE('x = ' || x);
9 DBMS_OUTPUT.PUT_LINE('echo.x = ' || echo.x);
10 END;
11
12 BEGIN
13 echo;
14 END;
15 /
x = 0
echo.x = 0
PL/SQL procedure successfully completed.
SQL>
例2-28では、ブロックおよびサブプログラムの両方にechoという名前を付けています。 ブロックおよびサブプログラムの両方で、xという変数を宣言しています。 サブプログラム内では、echo.xは、グローバル変数xではなく、ローカル変数xを参照します。
例2-28では、外側のブロックに対して2つのラベルcompute_ratioとanother_labelが存在します。 2番目のラベルは、内側のブロックで再利用されます。 内側のブロック内では、another_label.denominatorはローカル変数denominatorを参照し、グローバル変数denominatorを参照しません。このため、ZERO_DIVIDEエラーが発生します。
例2-28 複数の重複したラベルを使用するブロック
SQL> <<compute_ratio>> 2 <<another_label>> 3 DECLARE 4 numerator NUMBER := 22; 5 denominator NUMBER := 7; 6 BEGIN 7 <<another_label>> 8 DECLARE 9 denominator NUMBER := 0; 10 BEGIN 11 DBMS_OUTPUT.PUT_LINE('Ratio with compute_ratio.denominator = '); 12 DBMS_OUTPUT.PUT_LINE(numerator/compute_ratio.denominator); 13 14 DBMS_OUTPUT.PUT_LINE('Ratio with another_label.denominator = '); 15 DBMS_OUTPUT.PUT_LINE(numerator/another_label.denominator); 16 17 EXCEPTION 18 WHEN ZERO_DIVIDE THEN 19 DBMS_OUTPUT.PUT_LINE('Divide-by-zero error: can''t divide ' 20 || numerator || ' by ' || denominator); 21 WHEN OTHERS THEN 22 DBMS_OUTPUT.PUT_LINE('Unexpected error.'); 23 END inner_label; 24 END compute_ratio; 25 / Ratio with compute_ratio.denominator = 3.14285714285714285714285714285714285714 Ratio with another_label.denominator = Divide-by-zero error: cannot divide 22 by 0 PL/SQL procedure successfully completed. SQL>
変数の宣言時にデフォルト値を代入する(「変数」を参照)か、または変数の宣言後に代入文を使用して値を代入できます。 たとえば、次の文では変数bonusの古い値を上書きして、新しい値を代入します。
bonus := salary * 0.15;
代入演算子(:=)の後に続く式は、複雑なものでもかまいませんが、そのデータ型は変数のデータ型と同じか、または変数のデータ型に変換できるものである必要があります。
変数は、ブロックまたはサブプログラムに入るたびに初期化されます。 デフォルトでは、変数はNULLに初期化されます。 例2-29に示すように、変数を明示的に初期化しないかぎり、その値はNULLです。
例2-29 デフォルトでNULLに初期化される変数
SQL> DECLARE 2 counter INTEGER; 3 BEGIN 4 counter := counter + 1; 5 6 IF counter IS NULL THEN 7 DBMS_OUTPUT.PUT_LINE('counter is NULL.'); 8 END IF; 9 END; 10 / counter is NULL. PL/SQL procedure successfully completed. SQL>
予期しない結果を避けるため、値を代入する前に変数を参照しないでください。
ここでのトピック:
ブール変数に代入できるのは、リテラルまたは式の結果としての値TRUE、FALSEおよびNULLのみです。
例2-30では、ブール変数doneはデフォルトでNULLに初期化され、その後、リテラル値FALSEが代入され、リテラルのブール値と比較されて、ブール式の値が代入されています。
例2-30 ブール値の代入
SQL> DECLARE 2 done BOOLEAN; -- Initialize to NULL by default 3 counter NUMBER := 0; 4 BEGIN 5 done := FALSE; -- Assign literal value 6 WHILE done != TRUE -- Compare to literal value 7 LOOP 8 counter := counter + 1; 9 done := (counter > 500); -- Assign value of BOOLEAN expression 10 END LOOP; 11 END; 12 / PL/SQL procedure successfully completed. SQL>
SELECT INTO文を使用しても変数に値を代入できます。 例2-31に示すように、SELECTリストの項目ごとに、対応する型互換の変数がINTOリストに存在している必要があります。
例2-31 変数への問合せ結果の代入
SQL> DECLARE 2 emp_id employees.employee_id%TYPE := 100; 3 emp_name employees.last_name%TYPE; 4 wages NUMBER(7,2); 5 BEGIN 6 SELECT last_name, salary + (salary * nvl(commission_pct,0)) 7 INTO emp_name, wages 8 FROM employees 9 WHERE employee_id = emp_id; 10 11 DBMS_OUTPUT.PUT_LINE 12 ('Employee ' || emp_name || ' might make ' || wages); 13 END; 14 / Employee King might make 24000 PL/SQL procedure successfully completed. SQL>
SQLにはBOOLEAN型がないため、列の値を選択してBOOLEAN変数に代入することはできません。 変数の値が未定義の場合を含め、DML文での変数の代入の詳細は、「データ操作言語(DML)文」を参照してください。
最も単純なPL/SQL式は変数1つで構成され、その変数の値が式の値になります。 任意の複雑なPL/SQL式は、オペランドと演算子を使用して作成できます。 オペランドとは、変数、定数、リテラル、プレースホルダまたはファンクション・コールのことです。 演算子は、単項またはバイナリのいずれかで、それぞれ1つのオペランドまたは2つのオペランドに対して操作を実行します。 単項演算子の例としては、否定(-)があります。 バイナリ演算子の例としては、加算(+)があります。
単純な算術式の例を次に示します。
-X / 2 + 3
PL/SQLは、演算子が指定する方法でオペランドの値を組み合せて、式を評価します。 式は常に1つの値を戻します。 PL/SQLは、式の内容と、式が使用されているコンテキストに基づいてこの値のデータ型を決定します。
ここでのトピック:
連結演算子(||)は、ある文字列オペランドを別の文字列オペランドに追加します。 各文字列には、CHAR、VARCHAR2、CLOBまたはこれらと同等のUnicodeで使用可能な型を使用できます。 一方の文字列がCLOBの場合、結果は一時的なCLOBになります。それ以外の場合は、VARCHAR2値になります。
例2-32およびこのマニュアル内のその他の多くの例で、連結演算子を使用しています。
式内の演算は、優先順位に応じて評価されます。 表2-2に、優先順位の高い順に演算子を示します。 同じ優先順位の演算子は、特に順序を考慮せずに適用されます。
表2-2 演算子の優先順位
| 演算子 | 演算 |
|---|---|
|
|
指数 |
|
|
恒等、否定 |
|
|
乗算、除算 |
|
|
加算、減算、連結 |
|
|
比較 |
|
|
論理否定 |
|
|
論理積 |
|
|
論理和 |
カッコを使用すると、評価の順序を制御できます。 カッコがネストされている場合は、最も深くネストされた副式が最初に評価されます。 カッコを使用して評価の順序を制御する必要がない場合でも、カッコを使用してわかりやすくすることができます。 (例2-33のSQLの組込みファンクションTO_CHARは、引数に相当する文字を戻します。 TO_CHARの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)
例2-33 演算子の優先順位
SQL> DECLARE
2 salary NUMBER := 60000;
3 commission NUMBER := 0.10;
4 BEGIN
5 -- Division has higher precedence than addition:
6
7 DBMS_OUTPUT.PUT_LINE('5 + 12 / 4 = ' || TO_CHAR(5 + 12 / 4));
8 DBMS_OUTPUT.PUT_LINE('12 / 4 + 5 = ' || TO_CHAR(12 / 4 + 5));
9
10 -- Parentheses override default operator precedence:
11
12 DBMS_OUTPUT.PUT_LINE('8 + 6 / 2 = ' || TO_CHAR(8 + 6 / 2));
13 DBMS_OUTPUT.PUT_LINE('(8 + 6) / 2 = ' || TO_CHAR((8 + 6) / 2));
14
15 -- Most deeply nested subexpression is evaluated first:
16
17 DBMS_OUTPUT.PUT_LINE('100 + (20 / 5 + (7 - 3)) = '
18 || TO_CHAR(100 + (20 / 5 + (7 - 3))));
19
20 -- Parentheses, even when unnecessary, improve readability:
21
22 DBMS_OUTPUT.PUT_LINE('(salary * 0.05) + (commission * 0.25) = '
23 || TO_CHAR((salary * 0.05) + (commission * 0.25))
24 );
25
26 DBMS_OUTPUT.PUT_LINE('salary * 0.05 + commission * 0.25 = '
27 || TO_CHAR(salary * 0.05 + commission * 0.25)
28 );
29 END;
30 /
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
PL/SQL procedure successfully completed.
SQL>
論理演算子AND、ORおよびNOTは、表2-3に示す3値論理に従います。 ANDとORはバイナリ演算子、NOTは単項演算子です。
表2-3 論理真理値表
| x | y | x AND y | x OR y | NOT x |
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NULLを伴う式で予測不可能な結果が発生しないように注意してください。 詳細は、「比較文と条件文でのNULL値の扱い」を参照してください。
表2-3および例2-34に示されているように、両方のオペランドがTRUEである場合にのみ、ANDはTRUEを戻します。 (いくつかの例で、例2-34で作成されるprint_booleanプロシージャを使用しています。)
例2-34 AND演算子
SQL> CREATE OR REPLACE PROCEDURE print_boolean (
2 name VARCHAR2,
3 value BOOLEAN
4 ) IS
5 BEGIN
6 IF value IS NULL THEN
7 DBMS_OUTPUT.PUT_LINE (name || ' = NULL');
8 ELSIF value = TRUE THEN
9 DBMS_OUTPUT.PUT_LINE (name || ' = TRUE');
10 ELSE
11 DBMS_OUTPUT.PUT_LINE (name || ' = FALSE');
12 END IF;
13 END;
14 /
Procedure created.
SQL> DECLARE
2
3 PROCEDURE print_x_and_y (
4 x BOOLEAN,
5 y BOOLEAN
6 ) IS
7 BEGIN
8 print_boolean ('x', x);
9 print_boolean ('y', y);
10 print_boolean ('x AND y', x AND y);
11 END;
12
13 BEGIN
14 print_x_and_y (FALSE, FALSE);
15 print_x_and_y (TRUE, FALSE);
16 print_x_and_y (FALSE, TRUE);
17 print_x_and_y (TRUE, TRUE);
18
19 print_x_and_y (TRUE, NULL);
20 print_x_and_y (FALSE, NULL);
21 print_x_and_y (NULL, TRUE);
22 print_x_and_y (NULL, FALSE);
23 END;
24 /
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
PL/SQL procedure successfully completed.
SQL>
表2-3および例2-35に示されているように、一方のオペランドがTRUEである場合、ORはTRUEを戻します。 (例2-35では、例2-34で作成されたprint_booleanプロシージャを起動します。)
例2-35 OR演算子
SQL> DECLARE
2
3 PROCEDURE print_x_or_y (
4 x BOOLEAN,
5 y BOOLEAN
6 ) IS
7 BEGIN
8 print_boolean ('x', x);
9 print_boolean ('y', y);
10 print_boolean ('x OR y', x OR y);
11 END;
12
13 BEGIN
14 print_x_or_y (FALSE, FALSE);
15 print_x_or_y (TRUE, FALSE);
16 print_x_or_y (FALSE, TRUE);
17 print_x_or_y (TRUE, TRUE);
18
19 print_x_or_y (TRUE, NULL);
20 print_x_or_y (FALSE, NULL);
21 print_x_or_y (NULL, TRUE);
22 print_x_or_y (NULL, FALSE);
23 END;
24 /
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
PL/SQL procedure successfully completed.
SQL>
表2-3および例2-36に示されているように、オペランドがNULLでないかぎり、NOTはオペランドの反対の値を戻します。 NULLは値を持たないため、NOT NULLはNULLを戻します。 (例2-36では、例2-34で作成されたprint_booleanプロシージャを起動します。)
例2-36 NOT演算子
SQL> DECLARE
2
3 PROCEDURE print_not_x (
4 x BOOLEAN
5 ) IS
6 BEGIN
7 print_boolean ('x', x);
8 print_boolean ('NOT x', NOT x);
9 END;
10
11 BEGIN
12 print_not_x (TRUE);
13 print_not_x (FALSE);
14 print_not_x (NULL);
15 END;
16 /
x = TRUE
NOT x = FALSE
x = FALSE
NOT x = TRUE
x = NULL
NOT x = NULL
PL/SQL procedure successfully completed.
SQL>
ここでのトピック:
他のすべての演算子と同様に、論理演算子の評価の順序は、表2-2に示されている演算子の優先順位によって決まり、例2-37に示すように、カッコによって変更できます。 (例2-37では、例2-34で作成されたprint_booleanプロシージャを起動します。)
例2-37 論理演算子の評価の順序の変更
SQL> DECLARE 2 x BOOLEAN := FALSE; 3 y BOOLEAN := FALSE; 4 5 BEGIN 6 print_boolean ('NOT x AND y', NOT x AND y); 7 print_boolean ('NOT (x AND y)', NOT (x AND y)); 8 print_boolean ('(NOT x) AND y', (NOT x) AND y); 9 END; 10 / NOT x AND y = FALSE NOT (x AND y) = TRUE (NOT x) AND y = FALSE PL/SQL procedure successfully completed. SQL>
論理式を評価するときに、PL/SQLでは短絡評価を使用します。 これによって、PL/SQLは結果が判別できた時点でただちに式の評価を停止します。 そのため、評価を続ければエラーになるような式でも書くことができます。
例2-38では、短絡評価によって8行目の式でエラーが発生するのを回避しています。
例2-28 短絡評価
SQL> DECLARE
2 on_hand INTEGER := 0;
3 on_order INTEGER := 100;
4 BEGIN
5 -- Does not cause divide-by-zero error;
6 -- evaluation stops after first expression
7
8 IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN
9 DBMS_OUTPUT.PUT_LINE('On hand quantity is zero.');
10 END IF;
11 END;
12 /
On hand quantity is zero.
PL/SQL procedure successfully completed.
SQL>
on_handの値が0(ゼロ)の場合、左のオペランドはTRUEになるため、PL/SQLは右のオペランドを評価しません。 OR演算子を適用する前に両方のオペランドを評価した場合には、右のオペランドは0による除算エラーになります。
短絡評価は、PL/SQLのIF文、CASE文およびCASE式に適用されます。
比較演算子は式と式を比較します。 比較の結果は、常にTRUE、FALSEまたはNULLのいずれかです。 比較演算子は、一般に、SQL DML文のWHERE句と、条件制御文の中で使用します。
比較演算子は、次のとおりです。
関係演算子(表2-4を参照)
|
注意: 比較演算子にCLOB値を使用すると、一時的なLOB値が作成される場合があります。 一時表領域がこのような値を処理できる大きさであることを確認してください。 |
例2-39では、例2-34で作成されたprint_booleanプロシージャを起動し、関係演算子を含むいくつかの式の値を出力します。
例2-39 関係演算子
SQL> BEGIN
2 print_boolean ('(2 + 2 = 4)', 2 + 2 = 4);
3
4 print_boolean ('(2 + 2 <> 4)', 2 + 2 <> 4);
5 print_boolean ('(2 + 2 != 4)', 2 + 2 != 4);
6 print_boolean ('(2 + 2 ~= 4)', 2 + 2 ~= 4);
7 print_boolean ('(2 + 2 ^= 4)', 2 + 2 ^= 4);
8
9 print_boolean ('(1 < 2)', 1 < 2);
10
11 print_boolean ('(1 > 2)', 1 > 2);
12
13 print_boolean ('(1 <= 2)', 1 <= 2);
14
15 print_boolean ('(1 >= 1)', 1 >= 1);
16 END;
17 /
(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
PL/SQL procedure successfully completed.
SQL>
IS NULL演算子は、オペランドがNULLの場合はブール値TRUEを、NULLではない場合はFALSEを戻します。 NULL値が関係する比較は、常に結果がNULLになります。
値がNULLかどうかをテストするには、例2-34のプロシージャprint_booleanの6行目のように、IF value IS NULLを使用します。
LIKE演算子は、文字、文字列またはCLOB値をパターンと比較し、値がパターンと一致した場合はTRUE、一致しなかった場合はFALSEを戻します。
パターンには、アンダースコア(_)およびパーセント記号(%)の2種類の「ワイルドカード」文字を使用できます。 アンダースコアは1つの文字を表します。 パーセント記号(%)は0(ゼロ)個以上の文字を表します。
大/小文字が区別されます。 例2-40に示すように、文字列'Johnson'はパターン'J%s_n'に一致しますが、'J%S_N'には一致しません。
例2-40 LIKE演算子
SQL> DECLARE
2
3 PROCEDURE compare (
4 value VARCHAR2,
5 pattern VARCHAR2
6 ) IS
7 BEGIN
8 IF value LIKE pattern THEN
9 DBMS_OUTPUT.PUT_LINE ('TRUE');
10 ELSE
11 DBMS_OUTPUT.PUT_LINE ('FALSE');
12 END IF;
13 END;
14
15 BEGIN
16 compare('Johnson', 'J%s_n');
17 compare('Johnson', 'J%S_N');
18 END;
19 /
TRUE
FALSE
PL/SQL procedure successfully completed.
SQL>
パーセント記号やアンダースコアを検索するには、エスケープ文字を定義して、パーセント記号またはアンダースコアの前にそのエスケープ文字を挿入します。
例2-41では、バックスラッシュをエスケープ文字として使用しているため、文字列内のパーセント記号はワイルドカードとしての役割は果たしません。
例2-41 パターン内のエスケープ文字
SQL> DECLARE
2
3 PROCEDURE half_off (sale_sign VARCHAR2) IS
4 BEGIN
5 IF sale_sign LIKE '50\% off!' ESCAPE '\' THEN
6 DBMS_OUTPUT.PUT_LINE ('TRUE');
7 ELSE
8 DBMS_OUTPUT.PUT_LINE ('FALSE');
9 END IF;
10 END;
11
12 BEGIN
13 half_off('Going out of business!');
14 half_off('50% off!');
15 END;
16 /
FALSE
TRUE
PL/SQL procedure successfully completed.
SQL>
BETWEEN演算子は、指定された範囲に、ある値が含まれているかどうかをテストします。x BETWEEN a AND bは、x >= aおよびx <= bを意味します。
例2-42では、例2-34で作成されたprint_booleanプロシージャを起動し、BETWEEN演算子を含むいくつかの式の値を出力します。
例2-42 BETWEEN演算子
SQL> BEGIN
2 print_boolean ('2 BETWEEN 1 AND 3', 2 BETWEEN 1 AND 3);
3 print_boolean ('2 BETWEEN 2 AND 3', 2 BETWEEN 2 AND 3);
4 print_boolean ('2 BETWEEN 1 AND 2', 2 BETWEEN 1 AND 2);
5 print_boolean ('2 BETWEEN 3 AND 4', 2 BETWEEN 3 AND 4);
6 END;
7 /
2 BETWEEN 1 AND 3 = TRUE
2 BETWEEN 2 AND 3 = TRUE
2 BETWEEN 1 AND 2 = TRUE
2 BETWEEN 3 AND 4 = FALSE
PL/SQL procedure successfully completed.
SQL>
IN演算子は、セット・メンバーシップをテストします。x IN (set)は、xがsetのいずれかのメンバーと等しいことを意味します。
例2-43では、例2-34で作成されたprint_booleanプロシージャを起動し、IN演算子を含むいくつかの式の値を出力します。
例2-43 IN演算子
SQL> DECLARE
2 letter VARCHAR2(1) := 'm';
3 BEGIN
4 print_boolean (
5 'letter IN (''a'', ''b'', ''c'')',
6 letter IN ('a', 'b', 'c')
7 );
8
9 print_boolean (
10 'letter IN (''z'', ''m'', ''y'', ''p'')',
11 letter IN ('z', 'm', 'y', 'p')
12 );
13 END;
14 /
letter IN ('a', 'b', 'c') = FALSE
letter IN ('z', 'm', 'y', 'p') = TRUE
PL/SQL procedure successfully completed.
SQL>
例2-44は、setにNULL値が含まれている場合に発生する状況を示しています。 (例2-44では、例2-34で作成されたprint_booleanプロシージャを起動します。)
例2-44 NULL値を含む集合でのIN演算子の使用
SQL> DECLARE 2 a INTEGER; -- Initialized to NULL by default 3 b INTEGER := 10; 4 c INTEGER := 100; 5 BEGIN 6 print_boolean ('100 IN (a, b, c)', 100 IN (a, b, c)); 7 print_boolean ('100 NOT IN (a, b, c)', 100 NOT IN (a, b, c)); 8 9 print_boolean ('100 IN (a, b)', 100 IN (a, b)); 10 print_boolean ('100 NOT IN (a, b)', 100 NOT IN (a, b)); 11 12 print_boolean ('a IN (a, b)', a IN (a, b)); 13 print_boolean ('a NOT IN (a, b)', a NOT IN (a, b)); 14 END; 15 / 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 PL/SQL procedure successfully completed. SQL>
PL/SQLでは、SQL文の中でもプロシージャ文の中でも、変数と定数を比較できます。 これらの比較はブール式と呼ばれ、関係演算子で区切られた単純式またはコンポジット式で構成されます。 ブール式は一般に論理演算子AND、ORおよびNOTで結合されます。 ブール式の結果は常に、TRUE、FALSE、NULLのいずれかになります。
SQL文の中でブール式を使用して、表の中の文が影響を与える列を指定できます。 プロシージャ文では、条件制御の基盤としてブール式が使用されます。
ここでのトピック:
関係演算子を使用して数値を比較し、等しいか等しくないかを判定できます。 比較は量によるものです。つまり、片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。 たとえば、次のような代入文があるとします。
number1 := 75; number2 := 70;
次の式はTRUEになります。
number1 > number2
一般に、実数を比較して等しいかどうかを判定することはお薦めしません。 実数は近似値として格納されます。 たとえば、次のようなIF条件はTRUEにならない可能性があります。
DECLARE
fraction BINARY_FLOAT := 1/3;
BEGIN
IF fraction = 11/33 THEN
DBMS_OUTPUT.PUT_LINE('Fractions are equal (luckily!)');
END IF;
END;
/
文字値を比較して、等しいか等しくないかを判定できます。 デフォルトでは、比較は文字列の各バイトのバイナリ値に基づいて行われます。 たとえば、次のような代入文があるとします。
string1 := 'Kathy'; string2 := 'Kathleen';
次の式はTRUEになります。
string1 > string2
初期化パラメータNLS_COMP=ANSIを設定すると、NLS_SORT初期化パラメータで識別される照合順番を比較に使用できます。 照合順番とは、特定の範囲の数値コードが個々の文字に対応しているキャラクタ・セットの内部的な順序のことです。 内部的な順番を表す数値が他方の文字より大きい場合、その文字値はより大きいとみなされます。 この種の文字が照合順番に使用される場所については、言語ごとに規則が異なる場合があります。 たとえば、アクセント記号が付いた文字のソート順序は、バイナリ値が同じであってもデータベース・キャラクタ・セットに応じて異なることがあります。
NLS_SORTパラメータの値によっては、大/小文字およびアクセント記号の有無を区別しない比較を実行できます。 大/小文字を区別しない比較では、オペランドの文字の大/小文字が異なる場合でもTRUEが戻されます。 アクセント記号の有無を区別しない比較は、大/小文字を区別せず、オペランドのアクセント記号またはデリミタ文字が異なる場合でもTRUEが戻されます。 たとえば、大/小文字を区別しない比較では、'True'と'TRUE'の文字値は同じであるとみなされ、'Cooperate'、'Co-Operate'および'coöperate' の文字値もすべて同じであるとみなされます。 大/小文字を区別せずに比較するには、NLS_SORTパラメータの通常の値の末尾に_CIを付けます。 アクセント記号の有無を区別せずに比較するには、NLS_SORTの値の末尾に_AIを付けます。
文字値を比較する場合には、ベース型CHARとVARCHAR2の間にある意味上の違いを考慮する必要があります。 詳細は、「CHARとVARCHAR2のデータ型の違い」を参照してください。
多くの型は文字型に変換できます。 たとえば、CLOB変数を使用して比較、代入および他の文字操作を実行できます。 実行可能な変換の詳細は、「PL/SQLのデータ型変換」を参照してください。
日付も比較できます。 比較は時系列によってなされます。つまり、片方の日付がより新しければ、その日付はより大きいとみなされます。 たとえば、次のような代入文があるとします。
date1 := '01-JAN-91'; date2 := '31-DEC-90';
次の式はTRUEになります。
date1 > date2
比較する場合は、カッコを使用することをお薦めします。 たとえば次の式で、100 < taxはブール値になりますが、これは数値500と比較できないため、この式は無効です。
100 < tax < 500 -- not allowed
これをデバッグすれば、次の式になります。
(100 < tax) AND (tax < 500)
ブール変数自体を条件として使用できます。ブール変数をTRUE値またはFALSE値と比較する必要はありません。 例2-24では、ループは等価です。
例2-45 条件テストでのブール変数の使用
SQL> DECLARE 2 done BOOLEAN; 3 BEGIN 4 -- The following WHILE loops are equivalent 5 6 done := FALSE; 7 WHILE done = FALSE 8 LOOP 9 done := TRUE; 10 END LOOP; 11 12 done := FALSE; 13 WHILE NOT (done = TRUE) 14 LOOP 15 done := TRUE; 16 END LOOP; 17 18 done := FALSE; 19 WHILE NOT done 20 LOOP 21 done := TRUE; 22 END LOOP; 23 END; 24 / PL/SQL procedure successfully completed. SQL>
CASE文では、単純な式と検索式の2種類の式が使用されます。 これらの式は、その式が使用されるCASE文の種類に対応しています。 詳細は、「単純なCASE文の使用」を参照してください。
ここでのトピック:
単純なCASE式は、1つ以上の選択肢から結果を選択して戻します。 CASE式が複数の行にわたるブロックを含む場合でも、CASE式は代入やサブプログラム・コールなどの大きい文の一部を構成する1つの式です。 CASE式は選択子を使用します。選択子は、その値によって戻す代替アクションが決まる式です。
CASE式の書式は、例2-46に示すとおりです。 選択子(grade)の後に1つ以上のWHEN句があり、各句が順番にチェックされます。 選択子の値によって、どの句が評価されるかが決定されます。 選択子の値と最初に一致したWHEN句によって結果値が決定され、後続のWHEN句は評価されません。 一致する句がない場合は、オプションのELSE句が実行されます。
例2-46 CASE文でのWHEN句の使用
SQL> DECLARE
2 grade CHAR(1) := 'B';
3 appraisal VARCHAR2(20);
4 BEGIN
5 appraisal :=
6 CASE grade
7 WHEN 'A' THEN 'Excellent'
8 WHEN 'B' THEN 'Very Good'
9 WHEN 'C' THEN 'Good'
10 WHEN 'D' THEN 'Fair'
11 WHEN 'F' THEN 'Poor'
12 ELSE 'No such grade'
13 END;
14 DBMS_OUTPUT.PUT_LINE
15 ('Grade ' || grade || ' is ' || appraisal);
16 END;
17 /
Grade B is Very Good
PL/SQL procedure successfully completed.
SQL>
オプションのELSE句の機能は、IF文のELSE句に似ています。 選択子の値がWHEN句のオプションの1つでなければ、ELSE句が実行されます。 ELSE句が指定されておらず、一致するWHEN句がなければ、式はNULLを戻します。
検索CASE式を使用すると、1つの式を様々な値と比較するのではなく、異なる条件をテストできます。 この式の書式は、例2-47に示すとおりです。
検索CASE式には選択子はありません。 各WHEN句にはブール値を生成する検索条件が含まれており、単一のWHEN句で異なる変数または複数の条件をテストできます。
例2-47 CASE文での検索条件の使用
SQL> DECLARE
2 grade CHAR(1) := 'B';
3 appraisal VARCHAR2(120);
4 id NUMBER := 8429862;
5 attendance NUMBER := 150;
6 min_days CONSTANT NUMBER := 200;
7
8 FUNCTION attends_this_school (id NUMBER)
9 RETURN BOOLEAN IS
10 BEGIN
11 RETURN TRUE;
12 END;
13
14 BEGIN
15 appraisal :=
16 CASE
17 WHEN attends_this_school(id) = FALSE
18 THEN 'Student not enrolled'
19 WHEN grade = 'F' OR attendance < min_days
20 THEN 'Poor (poor performance or bad attendance)'
21 WHEN grade = 'A' THEN 'Excellent'
22 WHEN grade = 'B' THEN 'Very Good'
23 WHEN grade = 'C' THEN 'Good'
24 WHEN grade = 'D' THEN 'Fair'
25 ELSE 'No such grade'
26 END;
27 DBMS_OUTPUT.PUT_LINE
28 ('Result for student ' || id || ' is ' || appraisal);
29 END;
30 /
Result for student 8429862 is Poor (poor performance or bad attendance)
PL/SQL procedure successfully completed.
SQL>
検索条件は順番に評価されます。 各検索条件のブール値によって、どのWHEN句が実行されるかが決定されます。 検索条件がTRUEになると、そのWHEN句が実行されます。 WHEN句が1つでも実行された後は、後続の検索条件は評価されません。 TRUEになる検索条件がなければ、オプションのELSE句が実行されます。 WHEN句が実行されず、ELSE句が指定されていなければ、式の値はNULLとなります。
NULL値が関係する比較は、常に結果がNULLになります。
論理演算子NOTをNULL値に適用すると、NULLが戻ります。
条件制御文において条件がNULLになる場合、関連する一連の文は実行されません。
単純なCASE文中の式またはCASE式がNULLになる場合は、WHEN NULLを使用して一致させることができません。 かわりに、検索CASE構文をWHEN expression IS NULLとともに使用します。
例2-48では、xとyが等しくないため、一連の文が実行されることが予測されます。 ただし、NULL値は予測不可能です。 そのため、xとyが等しいかどうかは不明です。 したがって、IF条件はNULLになり、一連の文は実行されずにバイパスされます。
例2-48 等しくない比較でのNULL値
SQL> DECLARE 2 x NUMBER := 5; 3 y NUMBER := NULL; 4 BEGIN 5 IF x != y THEN -- yields NULL, not TRUE 6 DBMS_OUTPUT.PUT_LINE('x != y'); -- not executed 7 ELSIF x = y THEN -- also yields NULL 8 DBMS_OUTPUT.PUT_LINE('x = y'); 9 ELSE 10 DBMS_OUTPUT.PUT_LINE 11 ('Can''t tell if x and y are equal or not.'); 12 END IF; 13 END; 14 / Can't tell if x and y are equal or not. PL/SQL procedure successfully completed. SQL>
例2-49では、aとbが等しいため、一連の文が実行されることが予測されます。 ただし、等号条件が成立するかどうかは不明であるため、IF条件はNULLになり、一連の文は実行されずにバイパスされます。
例2-49 等しい比較でのNULL値
SQL> DECLARE 2 a NUMBER := NULL; 3 b NUMBER := NULL; 4 BEGIN 5 IF a = b THEN -- yields NULL, not TRUE 6 DBMS_OUTPUT.PUT_LINE('a = b'); -- not executed 7 ELSIF a != b THEN -- yields NULL, not TRUE 8 DBMS_OUTPUT.PUT_LINE('a != b'); -- not executed 9 ELSE 10 DBMS_OUTPUT.PUT_LINE('Can''t tell if two NULLs are equal'); 11 END IF; 12 END; 13 / Can't tell if two NULLs are equal PL/SQL procedure successfully completed. SQL>
ここでのトピック:
論理演算子NOTをNULL値に適用すると、NULLが戻されます。 このため、次の2つのIF文は必ずしも等価ではありません。
SQL> DECLARE 2 x INTEGER := 2; 3 Y INTEGER := 5; 4 high INTEGER; 5 BEGIN 6 IF x > y THEN high := x; 7 ELSE high := y; 8 END IF; 9 10 IF NOT x > y THEN high := y; 11 ELSE high := x; 12 END IF; 13 END; 14 / PL/SQL procedure successfully completed. SQL>
IF条件がFALSEまたはNULLになると、ELSE句内の一連の文が実行されます。 xとyのどちらもNULLではない場合、両方のIF文で同じ値がhighに代入されます。 ただし、xとyのどちらかがNULLの場合、1番目のIF文はyの値をhighに代入しますが、2番目のIF文はxの値をhighに代入します。
PL/SQLは長さが0(ゼロ)の文字値をすべてNULL値とみなします。 これには文字関数やブール式によって戻された値が含まれます。 たとえば、次の文ではターゲットの変数にNULLを代入します。
SQL> DECLARE
2 null_string VARCHAR2(80) := TO_CHAR('');
3 address VARCHAR2(80);
4 zip_code VARCHAR2(80) := SUBSTR(address, 25, 0);
5 name VARCHAR2(80);
6 valid BOOLEAN := (name != '');
7 BEGIN
8 NULL;
9 END;
10 /
PL/SQL procedure successfully completed.
SQL>
NULL文字列かどうかをテストする場合は、次のようにIS NULL演算子を使用してください。
IF v_string IS NULL THEN ...
連結演算子はNULLオペランドを無視します。 次に例を示します。
SQL> BEGIN
2 DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce');
3 END;
4 /
applesauce
PL/SQL procedure successfully completed.
SQL>
組込みファンクションに引数NULLが渡されると、次に示す場合を除いてNULL値が戻されます。
ファンクションDECODEは、先頭の引数を1つまたは複数の検索式と比較します。検索式は結果式と対になっています。 検索式や結果式はNULLの場合があります。 検索に成功すると、対応する結果が戻されます。 例2-50では、列manager_idがNULLの場合、DECODEは値'nobody'を戻します。
例2-50 DECODEファンクションに対する引数としてのNULL値
SQL> DECLARE 2 manager VARCHAR2(40); 3 name employees.last_name%TYPE; 4 BEGIN 5 -- NULL is a valid argument to DECODE. 6 -- In this case, manager_id is NULL 7 -- and the DECODE function returns 'nobody'. 8 9 SELECT DECODE(manager_id, NULL, 'nobody', 'somebody'), last_name 10 INTO manager, name 11 FROM employees 12 WHERE employee_id = 100; 13 14 DBMS_OUTPUT.PUT_LINE 15 (name || ' is managed by ' || manager); 16 END; 17 / King is managed by nobody PL/SQL procedure successfully completed. SQL>
先頭の引数がNULLの場合、ファンクションNVLは2番目の引数の値を戻します。 例2-51では、問合せで指定された列がNULLの場合、ファンクションは値-1を戻し、従業員が存在しないことを出力に示します。
例2-51 NVLファンクションに対する引数としてのNULL値
SQL> DECLARE 2 manager employees.manager_id%TYPE; 3 name employees.last_name%TYPE; 4 BEGIN 5 -- NULL is a valid argument to NVL. 6 -- In this case, manager_id is null 7 -- and the NVL function returns -1. 8 9 SELECT NVL(manager_id, -1), last_name 10 INTO manager, name 11 FROM employees 12 WHERE employee_id = 100; 13 14 DBMS_OUTPUT.PUT_LINE 15 (name || ' is managed by employee Id: ' || manager); 16 END; 17 / King is managed by employee Id: -1 PL/SQL procedure successfully completed. SQL>
2番目の引数がNULLの場合、ファンクションREPLACEはオプションの3番目の引数が存在するかどうかにかかわらず、1番目の引数の値を戻します。 たとえば、例2-52のREPLACEのコールは、old_stringの値を変更しません。
例2-52 REPLACEファンクションに対する2番目の引数としてのNULL値
SQL> DECLARE
2 string_type VARCHAR2(60);
3 old_string string_type%TYPE := 'Apples and oranges';
4 v_string string_type%TYPE := 'more apples';
5
6 -- NULL is a valid argument to REPLACE,
7 -- but does not match anything,
8 -- so no replacement is done.
9
10 new_string string_type%TYPE := REPLACE(old_string, NULL, v_string);
11 BEGIN
12 DBMS_OUTPUT.PUT_LINE('Old string = ' || old_string);
13 DBMS_OUTPUT.PUT_LINE('New string = ' || new_string);
14 END;
15 /
Old string = Apples and oranges
New string = Apples and oranges
PL/SQL procedure successfully completed.
SQL>
3番目の引数がNULLの場合、REPLACEは、1番目の引数から2番目の引数をすべて削除したものを戻します。 たとえば、例2-53のREPLACEのコールは、dashed_stringのダッシュを別の文字で置き換えるのではなく、削除します。
例2-53 REPLACEファンクションに対する3番目の引数としてのNULL値
SQL> DECLARE
2 string_type VARCHAR2(60);
3 dashed string_type%TYPE := 'Gold-i-locks';
4
5 -- When the substitution text for REPLACE is NULL,
6 -- the text being replaced is deleted.
7
8 name string_type%TYPE := REPLACE(dashed, '-', NULL);
9 BEGIN
10 DBMS_OUTPUT.PUT_LINE('Dashed name = ' || dashed);
11 DBMS_OUTPUT.PUT_LINE('Dashes removed = ' || name);
12 END;
13 /
Dashed name = Gold-i-locks
Dashes removed = Goldilocks
PL/SQL procedure successfully completed.
SQL>
2番目の引数と3番目の引数がNULLの場合、REPLACEは単に1番目の引数を戻します。
PL/SQLには、PL/SQL例外処理コードで使用するためのSQLCODEとSQLERRMの2つの組込みエラー・レポート・ファンクションがあります。 詳細は、「SQLCODEファンクション」および「SQLERRMファンクション」を参照してください。
SQLCODEまたはSQLERRMファンクションは、SQL文では使用できません。
PL/SQL式では、次のファンクションを除くすべてのSQLファンクションを使用できます。
集計ファンクション(AVG、COUNTなど)
分析ファンクション(LAG、RATIO_TO_REPORTなど)
コレクション・ファンクション(CARDINALITY、SETなど)
データ・マイニング・ファンクション(CLUSTER_ID、FEATURE_VALUEなど)
エンコーディング・ファンクションおよびデコーディング・ファンクション(DECODE、DUMPなど)
モデル・ファンクション(ITERATION_NUMBER、PREVIOUSなど)
オブジェクト参照ファンクション(REF、VALUEなど)
XMLファンクション(APPENDCHILDXML、EXISTSNODEなど)
次の変換ファンクション:
BIN_TO_NUM
CAST
RAWTONHEX
ROWIDTONCHAR
その他の該当するファンクション:
CUBE_TABLE
DATAOBJ_TO_PARTITION
LNNVL
SYS_CONNECT_BY_PATH
SYS_TYPEID
WIDTH_BUCKET
PL/SQLでは、引数および結果がBINARY_INTEGERであるBITANDのオーバーロードがサポートされています。
PL/SQL式でRAWTOHEXファンクションを使用すると、データ型RAWの引数が受け入れられ、その引数の値を構成するバイトの16進表現でVARCHAR2値が戻されます。 RAW以外の型の引数は、RAWに暗黙的に変換できる場合にのみ指定できます。 この変換は、HEXTORAWファンクションの有効な引数であるCHAR、VARCHAR2およびLONGの値と、最大16380バイトのLONG RAWおよびBLOBの値に対して実行可能です。
|
参照: SQLファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
条件付きコンパイルを使用すると、ソース・コードを削除することなく、PL/SQLアプリケーションの機能をカスタマイズできます。 たとえば、条件付きコンパイルを使用して、PL/SQLアプリケーションを次のようにカスタマイズできます。
最新のリリースのデータベースでは最新の機能を利用し、古いリリースのデータベースに対しては、新しい機能を無効にしてそのアプリケーションを実行します。
開発環境ではデバッグ機能またはトレース機能をアクティブ化し、本番サイトでの実行では、アプリケーション内でその機能を隠ぺいします。
ここでのトピック:
条件付きコンパイルでは、選択ディレクティブ、問合せディレクティブおよびエラー・ディレクティブを使用してコンパイルのソース・テキストを指定します。 問合せディレクティブでは、PLSQL_CCFLAGSコンパイル・パラメータ(「PL/SQLユニットおよびコンパイル・パラメータ」を参照)の名前/値ペアによって設定された値にアクセスします。 選択ディレクティブでは、問合せディレクティブまたは静的パッケージ定数をテストできます。
DBMS_DB_VERSIONパッケージでは、条件付きコンパイルに使用できるデータベースのバージョンおよびリリース定数が提供されます。 DBMS_PREPROCESSORパッケージでは、PL/SQLユニットの条件付きコンパイル・ディレクティブによって選択される処理後のソース・テキストにアクセスするためのサブプログラムが提供されます。
ここでのトピック:
条件付きコンパイルのトリガー文字$で、これによってアプリケーションがコンパイルされる前に処理されるコードが識別されます。 条件付きコンパイル制御トークンの形式は次のとおりです。
preprocessor_control_token ::= $plsql_identifier
$は識別子名の先頭に置く必要があり、$と名前の間に空白を入れることはできません。 $は識別子名に埋め込むこともできますが、特別な意味は持ちません。 予約済のプリプロセッサ制御トークンは、$IF、$THEN、$ELSE、$ELSIF、$ENDおよび$ERRORです。 条件付きコンパイル制御トークンの使用例は、例2-56を参照してください。
条件付きコンパイルの選択ディレクティブでは、静的な式を評価して、コンパイルに含めるテキストを判定します。 選択ディレクティブの形式は次のとおりです。
$IF boolean_static_expression $THEN text [$ELSIF boolean_static_expression $THEN text] [$ELSE text] $END
boolean_static_expressionは、静的なBOOLEAN式である必要があります。 静的なBOOLEAN式の説明は、「条件付きコンパイルでの静的な式の使用」を参照してください。 PL/SQLのIF-THEN制御構造の詳細は、「条件テスト(IF文およびCASE文)」を参照してください。
エラー・ディレクティブ$ERRORでは、ユーザー定義の例外を呼び出します。形式は次のとおりです。
$ERROR varchar2_static_expression $END
varchar2_static_expressionは、静的なVARCHAR2式である必要があります。 静的なVARCHAR2式の説明は、「条件付きコンパイルでの静的な式の使用」を参照してください。 また、例2-55を参照してください。
問合せディレクティブは、コンパイル環境のチェックに使用します。 問合せディレクティブの形式は次のとおりです。
inquiry_directive ::= $$id
問合せディレクティブは、「条件付きコンパイルでの事前定義問合せディレクティブの使用」に示すとおり、事前定義またはユーザー定義にできます。 次に、条件付きコンパイルが問合せディレクティブを解決しようとする場合の処理フローの順序を示します。
idは、$$idの形式で、問合せディレクティブとして検索キーに使用します。
2パス・アルゴリズムは、次のように進行します。
PLSQL_CCFLAGSコンパイル・パラメータの文字列が右から左へスキャンされ、idで一致名(大/小文字を区別しない)が検索されて、検出されると完了します。
事前定義された問合せディレクティブが検索され、検出されると完了します。
$$idを値に解決できない場合は、ソース・テキストがラップされていなくてもPLW-6003警告メッセージがレポートされます。 リテラルNULLは、未定義の問合せディレクティブの値として代入されます。 PL/SQLコードがラップされている場合は、未定義の問合せディレクティブが示されないように、警告メッセージが無効になります。
たとえば、次のようなセッション設定があるとします。
ALTER SESSION SET PLSQL_CCFLAGS = 'plsql_ccflags:true, debug:true, debug:0';
$$debugの値は0で、$$plsql_ccflagsの値はTRUEです。 $$plsql_ccflagsの値は、PLSQL_CCFLAGSコンパイラ・パラメータの値内のユーザー定義のPLSQL_CCFLAGSを解決します。 これは、ユーザー定義のディレクティブは事前定義のディレクティブをオーバーライドするためです。
次のセッション設定について考えてみます。
ALTER SESSION SET PLSQL_CCFLAGS = 'debug:true'
$$debugの値はTRUE、$$plsql_ccflagsの値は'debug:true'、$$my_idの値はリテラルNULLです。$$my_idを使用すると、ソース・テキストがラップされていなくても、PLW-6003が呼び出されます。
問合せディレクティブの使用例は、例2-56を参照してください。
条件式で使用できる事前定義問合せディレクティブ名は、次のとおりです。
行番号を示すPLS_INTEGERリテラル値であるPLSQL_LINEは、現行のPL/SQLユニットの$$PLSQL_LINEを参照します。
条件式の$$PLSQL_LINEの例を次に示します。
$IF $$PLSQL_LINE = 32 $THEN ...
VARCHAR2リテラル値であるPLSQL_UNITは、現行のPL/SQLユニットを示しています。
名前付きPL/SQLユニットの場合は、$$PLSQL_UNITにユニット名が含まれますが、ユニット名に限定されない場合があります。 無名ブロックの場合は、$$PLSQL_UNITに空の文字列が含まれます。
条件式の$$PLSQL_UNITの例を次に示します。
IF $$PLSQL_UNIT = 'AWARD_BONUS' THEN ...
前述の例は、通常のPL/SQLでのPLSQL_UNITの使用を示しています。 $$PLSQL_UNIT = 'AWARD_BONUS'は静的な式ではなくVARCHAR2の比較であるため、$IFではサポートされません。 PLSQL_UNITでの有効な$IFの使用方法の1つに、次のように無名ブロックを決定することがあります。
$IF $$PLSQL_UNIT IS NULL $THEN ...
PL/SQLコンパイル・パラメータ
リテラルPLSQL_LINEおよびPLSQL_UNITの値は、コンパイル・パラメータPLSQL_CCFLAGSで明示的に定義できます。 コンパイル・パラメータの詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。
条件付きコンパイルの処理では、コンパイラで完全に評価できる静的な式のみが使用できます。 変数への参照を含むすべての式またはPL/SQLの実行が必要なファンクションは、コンパイル中には使用できず、評価されません。 PL/SQLのデータ型の詳細は、「事前定義のPL/SQLのスカラー・データ型およびサブタイプ」を参照してください。
静的な式とは、静的なBOOLEAN、PLS_INTEGERまたはVARCHAR2式のいずれかです。 パッケージで宣言される静的定数も静的な式です。
ここでのトピック:
静的なBOOLEAN式には次のものが含まれます。
TRUE、FALSEおよびリテラルNULL
xおよびyは、静的なPLS_INTEGER式です。
x > y
x < y
x >= y
x <= y
x = y
x <> y
xおよびyは、PLS_INTEGERブール式です。
NOT x
x AND y
x OR y
x > y
x >= y
x = y
x <= y
x <> y
xは静的な式です。
x IS NULL
x IS NOT NULL
静的なPLS_INTEGER式には次のものが含まれます。
-2147483648から2147483647およびリテラルNULL
静的なVARCHAR2式には次のものが含まれます。
'abcdef'
'abc' || 'def'
リテラルNULL
TO_CHAR(x)(xは静的なPLS_INTEGER式)
TO_CHAR(x f, n)(xは静的なPLS_INTEGER式で、fとnは静的なVARCHAR2式)
x || y(xおよびyは、静的なVARCHAR2式またはPLS_INTEGER式)
static_constant CONSTANT data_type := static_expression;
有効な静的定数の宣言は、次のとおりです。
宣言されたdata_typeとstatic_expressionの型が同じ場合
static_expressionが静的な式である場合
data_typeがBOOLEANまたはPLS_INTEGERのいずれかである場合
静的定数はパッケージ仕様部で宣言する必要があり、package_nameパッケージ本体内にある場合でも、package_name.constant_nameとして参照する必要があります。
静的パッケージ定数が、PL/SQLユニットで有効な選択ディレクティブのBOOLEAN式として使用されると、条件付きコンパイルのメカニズムによって、参照されるパッケージへの依存性が自動的に生成されます。 パッケージが変更されると依存ユニットは無効になり、再コンパイルして変更を取得する必要があります。 依存性を生成できるのは、有効な静的な式のみです。
複数のPL/SQLユニットの条件付きコンパイルを制御する静的定数を持つパッケージを使用する場合は、パッケージ仕様部のみを作成し、複数の依存性のために、そのパッケージ仕様部を条件付きコンパイルの制御専用にします。 個々のユニットの条件付きコンパイルを制御するには、PL/SQLコンパイル・パラメータPLSQL_CCFLAGSに特定のフラグを設定できます。 PL/SQLコンパイル・パラメータの詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。
例2-54では、my_debugパッケージは、デバッグを制御し、複数のPL/SQLユニットをトレースするための定数を定義します。 この例では、定数debugおよびtraceはプロシージャmy_proc1およびmy_proc2の静的な式で使用され、プロシージャからの依存性をmy_debugに生成します。
例2-54 静的定数の使用
SQL> CREATE PACKAGE my_debug IS
2 debug CONSTANT BOOLEAN := TRUE;
3 trace CONSTANT BOOLEAN := TRUE;
4 END my_debug;
5 /
Package created.
SQL> CREATE PROCEDURE my_proc1 IS
2 BEGIN
3 $IF my_debug.debug $THEN
4 DBMS_OUTPUT.put_line('Debugging ON');
5 $ELSE
6 DBMS_OUTPUT.put_line('Debugging OFF');
7 $END
8 END my_proc1;
9 /
Procedure created.
SQL> CREATE PROCEDURE my_proc2 IS
2 BEGIN
3 $IF my_debug.trace $THEN
4 DBMS_OUTPUT.put_line('Tracing ON');
5 $ELSE DBMS_OUTPUT.put_line('Tracing OFF');
6 $END
7 END my_proc2;
8 /
Procedure created.
SQL>
定数の値の1つを変更すると、パッケージのすべての依存ユニットが新しい値で再コンパイルされます。 たとえば、debugの値をFALSEに変更すると、my_proc1がデバッグ・コードなしで再コンパイルされます。my_proc2も再コンパイルされますが、traceの値が変更されていないため、my_proc2は変更されません。
DBMS_DB_VERSIONパッケージは、条件付きコンパイルの単純な選択を行う場合に役立つ定数を提供します。 PLS_INTEGER定数VERSIONおよびRELEASEは、現行のOracle Databaseバージョンとリリース番号を識別します。 ブール定数VER_LE_9、VER_LE_9_1、VER_LE_9_2、VER_LE_10、VER_LE_10_1およびVER_LE_10_2は、次のように、TRUEまたはFALSEと評価されます。
VER_LE_vは、データベース・バージョンがv以下の場合にTRUEと評価され、そうでない場合はFALSEと評価されます。
VER_LE_v_rは、データベース・バージョンがv以下で、リリースがr以下の場合にTRUEと評価され、そうでない場合はFALSEと評価されます。
Oracle Database 10gリリース1(10.1)以下を表す定数はすべてFALSEになります。
例2-55に、条件付きコンパイルでのDBMS_DB_VERSION定数の使用例を示します。 Oracle Databaseのバージョンとリリースの両方がチェックされます。 ここでは、$ERRORの使用例も示します。
例2-55 DBMS_DB_VERSION定数の使用
SQL> BEGIN
2 $IF DBMS_DB_VERSION.VER_LE_10_1 $THEN
3 $ERROR 'unsupported database release'
4 $END
5 $ELSE
6 DBMS_OUTPUT.PUT_LINE
7 ('Release ' || DBMS_DB_VERSION.VERSION || '.' ||
8 DBMS_DB_VERSION.RELEASE || ' is supported.');
9
10 -- This COMMIT syntax is newly supported in 10.2:
11 COMMIT WRITE IMMEDIATE NOWAIT;
12 $END
13 END;
14 /
Release 11.1 is supported.
PL/SQL procedure successfully completed.
SQL>
DBMS_DB_VERSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
この項では、条件付きコンパイルの使用例を示します。
ここでのトピック:
例2-56では、BINARY_DOUBLEデータ型をデータベースのPL/SQLユニットの計算で使用できるかどうかを、条件付きコンパイルを使用して判断します。 BINARY_DOUBLEデータ型は、10g以上のデータベースのバージョンでのみ使用できます。
例2-56 データベースのバージョンでの条件付きコンパイルの使用
SQL> -- Set flags for displaying debugging code and tracing info:
SQL>
SQL> ALTER SESSION SET PLSQL_CCFLAGS =
2 'my_debug:FALSE, my_tracing:FALSE';
Session altered.
SQL>
SQL> CREATE OR REPLACE PACKAGE my_pkg AS
2 SUBTYPE my_real IS
3 $IF DBMS_DB_VERSION.VERSION < 10 $THEN
4 NUMBER;
5 -- Check database version
6 $ELSE
7 BINARY_DOUBLE;
8 $END
9
10 my_pi my_real;
11 my_e my_real;
12 END my_pkg;
13 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY my_pkg AS
2 BEGIN
3 -- Set values for future calculations based on DB version
4
5 $IF DBMS_DB_VERSION.VERSION < 10 $THEN
6 my_pi := 3.14159265358979323846264338327950288420;
7 my_e := 2.71828182845904523536028747135266249775;
8 $ELSE
9 my_pi := 3.14159265358979323846264338327950288420d;
10 my_e := 2.71828182845904523536028747135266249775d;
11 $END
12 END my_pkg;
13 /
Package body created.
SQL> CREATE OR REPLACE PROCEDURE circle_area(radius my_pkg.my_real) IS
2 my_area my_pkg.my_real;
3 my_data_type VARCHAR2(30);
4 BEGIN
5 my_area := my_pkg.my_pi * radius;
6
7 DBMS_OUTPUT.PUT_LINE
8 ('Radius: ' || TO_CHAR(radius) || ' Area: ' || TO_CHAR(my_area));
9
10 $IF $$my_debug $THEN
11 -- If my_debug is TRUE, run debugging code
12 SELECT DATA_TYPE INTO my_data_type
13 FROM USER_ARGUMENTS
14 WHERE OBJECT_NAME = 'CIRCLE_AREA'
15 AND ARGUMENT_NAME = 'RADIUS';
16
17 DBMS_OUTPUT.PUT_LINE
18 ('Data type of the RADIUS argument is: ' || my_data_type);
19 $END
20 END;
21 /
Procedure created.
SQL>
DBMS_PREPROCESSORサブプログラムは、条件付きコンパイル・ディレクティブの処理後に、PL/SQLユニットの処理後のソース・テキストを印刷または取り出します。 この処理後のテキストは、有効なPL/SQLユニットのコンパイルに使用する実際のソースです。 例2-57に、PRINT_POST_PROCESSED_SOURCEプロシージャで例2-56のmy_pkgの処理後の形式を印刷する方法を示します。
例2-57 PRINT_POST_PROCESSED_SOURCEを使用したソース・コードの表示
SQL> CALL DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE 2 ('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. SQL>
PRINT_POST_PROCESSED_SOURCEは、非選択テキストを空白に置き換えます。 処理後のテキストに含まれない例2-56のコードの行は、空白行として表されます。 DBMS_PREPROCESSORパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
条件付きコンパイル・ディレクティブは、オブジェクト型の仕様部やスキーマ・レベルのネストした表またはVARRAYの仕様部では使用できません。 依存する型の属性構造および依存する表の列構造は、オブジェクト型の仕様部で指定された属性構造によって決定されます。 オブジェクト型の属性構造に対するすべての変更は、それらの変更が依存オブジェクトに適用されるように、決められた方法で実行される必要があります。 変更を適用するには、SQLのALTER TYPE ATTRIBUTE文を使用します。 プリプロセッサ・ディレクティブを使用すると、ALTER TYPE ATTRIBUTE文を使用しなくても、オブジェクト型の属性構造を変更できます。 その結果、依存オブジェクトが非同期になったり、依存表がアクセス不可になる場合があります。
SQLパーサーでは、CREATE OR REPLACE文や無名ブロックの実行などのSQL操作の実行時に、ディレクティブの配置についての制限があります。 これらのSQL操作の実行時、最初の条件付きコンパイル・ディレクティブの位置について、SQLパーサーでは次の制限があります。
条件付きコンパイル・ディレクティブは、オブジェクト型の仕様部やスキーマ・レベルのネストした表またはVARRAYの仕様部では使用できません。
パッケージ仕様部、パッケージ本体、型本体および仮パラメータがないスキーマ・レベルのサブプログラムでは、最初の条件付きコンパイル・ディレクティブが、キーワード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の直後またはキーワードDECLAREの直後に配置される場合があります。
無名ブロックでプレースホルダが使用される場合、条件付きコンパイル内ではこの配置は行われません。 次に例を示します。
BEGIN
:n := 1; -- valid use of placeholder
$IF ... $THEN
:n := 1; -- invalid use of placeholder
$END
PL/SQLを使用するとデータベースから直接Webページを生成するアプリケーションを作成できるため、データベースをWeb上で使用可能にし、事務管理部門のデータベースをイントラネット上でアクセス可能にすることができます。
PL/SQL Webアプリケーションのプログラム・フローは、CGI PERLスクリプトのプログラム・フローに似ています。 通常、開発者はCGIスクリプトを使用してWebページを動的に作成しますが、多くの場合それらのスクリプトはデータベースへのアクセスに適していません。 PL/SQLストアド・サブプログラムでWebコンテンツを配信することによって、強力で柔軟なデータベース処理が実現されます。 たとえば、DML、動的SQLおよびカーソルを使用できます。 各HTTPリクエストを処理する新しいCGIプロセスをforkするためのプロセス・オーバーヘッドを解消することもできます。
PL/SQL GatewayとPL/SQL Web Toolkitを使用して、完全にWebブラウザ・ベースのアプリケーションをPL/SQLに実装できます。
PL/SQL Gatewayを使用すると、HTTPリスナーを介してWebブラウザでPL/SQLストアド・サブプログラムを起動できます。PL/SQL Gatewayの1つの実装であるmod_plsqlはOracle HTTP Serverのプラグインであり、WebブラウザでPL/SQLストアド・サブプログラムを起動できるようにします。
PL/SQL Web Toolkitは、実行時にmod_plsqlによって起動されるストアド・サブプログラムを使用するための一般的なインタフェースを提供する一連のPL/SQLパッケージです。
|
参照: Webアプリケーションの作成の詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。 |
PL/SQL Server Pages(PSP)を使用すると、Webページを動的コンテンツで開発できます。 これは、Webページ用にHTMLコードを一度に1行ずつ書き出すストアド・サブプログラムをコーディングする方法の代替手段です。
特殊なタグを使用すると、PL/SQLスクリプトをHTMLソース・コードに埋め込むことができます。 スクリプトは、ページがブラウザなどのWebクライアントによって要求されたときに実行されます。 スクリプトは、パラメータ、データベースへの問合せまたは更新を受け入れることが可能で、結果を示すカスタマイズ済のページを表示できます。
開発中、PSPはページ・レイアウト用の静的部分およびコンテンツ用の動的部分を持つテンプレートのように動作できます。 任意のHTMLオーサリング・ツールを使用してレイアウトを設計できます。プレースホルダは動的コンテンツ用に残します。 次に、コンテンツを生成するPL/SQLスクリプトを作成できます。 終了した後、作成したPSPファイルをストアド・サブプログラムとして単にデータベースにロードします。
|
参照: Web Server Pagesの作成の詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。 |