この章では、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
x
E
y
は、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アドバンスト・アプリケーション開発者ガイド』を参照してください。 |