| Oracle Database PL/SQLユーザーズ・ガイドおよびリファレンス 10g リリース2(10.2) B19257-01 |
|
前の章では、PL/SQLの概要を示しました。この章では、PL/SQLを詳細に説明します。他のプログラミング言語と同様に、PL/SQLにはキャラクタ・セット、予約語、デリミタ、データ型および一定の構文規則があります。
この章の項目は、次のとおりです。
PL/SQLプログラムは、特定のキャラクタ・セットを使用したテキストとして作成されます。
A〜Zおよびa〜z
0〜 9
( ) + - * / < > = ! ~ ^ ; : . ' @ % , " # $ & _ | { } ? [ ]
PL/SQLキーワードは大/小文字が区別されないため、文字列リテラルと文字リテラルの中を除き、小文字の英字は対応する大文字の英字と等価です。
PL/SQLテキストの行には字句単位と呼ばれる文字のグループがあります。
わかりやすくするために、字句単位は空白で区切ることができます。実際には、隣接する識別子は、空白またはデリミタで区切る必要があります。次の行は予約語のENDとIFが結合されているため、不正です。
IF x > y THEN high := x; ENDIF; -- 不正です。END IFとする必要があります。
文字列リテラルとコメントの場合を除き、字句単位の中に空白を埋め込むことはできません。たとえば、次の行は代入を表すコンパウンド記号(:=)が分かれているため、不正です。
count : = count + 1; -- 不正です。 :=とする必要があります。
構造を示すために、改行で行を分けたり、空白またはタブで行にインデントを付けることができます。次に示す最初のIF文は、このような方法で形式を整えることによってより見やすくできます。
IF x>y THEN max:=x;ELSE max:=y;END IF;
次の文のほうがより見やすくなります。
デリミタは、PL/SQLにとって特別な意味を持つ単純記号またはコンパウンド記号です。たとえば、デリミタを使用して加算や減算などの算術演算を表現できます。表2-1に、PL/SQLのデリミタのリストを示します。
識別子を使用して、定数、変数、例外、カーソル、カーソル変数、サブプログラム、パッケージなどのPL/SQLプログラムに名前を付けることができます。次に識別子の例をいくつか示します。
識別子は英字1文字でもかまいませんが、後に英字、数字、ドル記号、アンダースコアおよびシャープ記号を続けることもできます。次の例のように、ハイフン、スラッシュ、空白などの文字は使用できません。
mine&yours: アンパサンドがあるため使用不可
debit-amount: ハイフンがあるため使用不可
on/off: スラッシュがあるため使用不可
user id: スペースがあるため使用不可
ドル記号、アンダースコアおよびシャープ記号を隣接して使用したり、先頭以外の位置で使用することができます。
識別子では大文字と小文字が使用でき、両者の混用もできます。PL/SQLでは、文字列リテラルと文字リテラルの中を除いて、大/小文字は区別されません。したがって、2つの識別子の違いが英字の大/小文字の違いのみであれば、PL/SQLは同じ識別子とみなします。
識別子のサイズは30文字以内にする必要があります。ドル記号、アンダースコアおよびシャープ記号を含むすべての文字が意味を持ちます。たとえば、PL/SQLは、次の2つの識別子を別のものとして扱います。
識別子は、内容がわかりやすいものにしてください。cpmのようなあいまいな名前は避けます。かわりに、cost_per_thousandのように意味のわかりやすい名前を使用してください。
識別子には、PL/SQLに対して構文上の特別な意味を持つ予約語があります。たとえば、BEGINとENDは予約語です。一般に、予約語は区別しやすくするために大文字で書かれています。
予約語を再定義しようとするとコンパイル・エラーが発生します。ただし、識別子の中に予約語を埋め込むことはできます。次に例を示します。
DECLARE -- end BOOLEAN; the use of "end" is not allowed; causes compilation error end_of_game BOOLEAN; -- allowed
予約語の他に、PL/SQLで特別な意味を持つキーワードがあります。PL/SQLのキーワードを識別子に使用することはできますが、お薦めしません。PL/SQLの予約語とキーワードのリストは、表D-1「PL/SQLの予約語」および表D-2「PL/SQLのキーワード」を参照してください。
例外INVALID_NUMBERなど、パッケージSTANDARDでグローバルに宣言されている識別子は、再宣言できます。ただし、事前定義の識別子を再宣言すると、ローカルな宣言がグローバルな宣言をオーバーライドするためエラーが発生しやすくなります。
柔軟性を高めるために、PL/SQLでは識別子を二重引用符で囲むことができます。通常は、このようにする必要はありませんが、ときには便利な場合もあります。二重引用符で囲んだ識別子には、空白など、二重引用符を除くすべての印字可能文字を任意に並べて入れることができます。したがって、次の識別子は有効です。
二重引用符で囲んだ識別子の最大サイズは、二重引用符を数えずに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
Eは、10の累乗を意味します。次の例で示すように、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の場合もあります。例2-1を参照してください。有効範囲外の結果の詳細は、「NUMBERデータ型」を参照してください。
DECLARE n NUMBER; -- declare n of NUMBER datatype BEGIN n := -9.999999E-130; -- valid n := 9.999E125; -- valid -- n := 10.0E125; -- invalid, "numeric overflow or underflow" END; /
例2-2に示すように、実数リテラルには、後ろにfまたはd文字を付けて、BINARY_FLOATまたはBINARY_DOUBLE型を指定できます。
DECLARE x BINARY_FLOAT := sqrt(2.0f); -- single-precision floating-point number y BINARY_DOUBLE := sqrt(2.0d); -- double-precision floating-point number BEGIN NULL; END; /
文字リテラルは引用符(アポストロフィ)で囲まれた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つのリテラルを異なるものとして扱います。
文字列の中でアポストロフィを表現する場合は、引用符を2つ書きます。これは二重引用符を書く場合とは違う意味を持ちます。
複雑なリテラル内で引用符を二重にする場合(特にSQL文を表すもの)は、注意が必要です。次の表記法を使用して、リテラルに独自のデリミタ文字を定義することもできます。デリミタ文字には、文字列に含まれていない文字を使用します。これによって、リテラル内の引用符をエスケープする必要がなくなります。
-- q'!...!' notation allows the of use single quotes
-- inside the literal
string_var := q'!I'm a string, you're a string.!';
デリミタ[、{、<、(を]、}、>、)とペアで使用すると、'INVALID'の前後の引用符を二重にすることなく、SQL文を表す文字列リテラルをサブプログラムに渡すことができます。
NCHARリテラルおよびNVARCHAR2リテラルの前には、qではなくnqを付けます。
NCHARデータ型およびUnicode文字列の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。
ブール・リテラルとは、事前定義の値TRUE、FALSEおよびNULLのことです。NULLは、存在しない値、不明な値または適用できない値を示します。ブール・リテラルは値であり、文字列ではないことに注意してください。たとえば、TRUEは数値25と同じように1つの値です。
日時リテラルには、データ型に応じて様々な形式があります。次に例を示します。
DECLARE d1 DATE := DATE '1998-12-25'; t1 TIMESTAMP := TIMESTAMP '1997-10-22 13:01:01'; t2 TIMESTAMP WITH TIME ZONE := TIMESTAMP '1997-01-31 09:26:56.66 +02:00'; -- Three years and two months -- For greater precision, we would use the day-to-second interval i1 INTERVAL YEAR TO MONTH := INTERVAL '3-2' YEAR TO MONTH; -- Five days, four hours, three minutes, two and 1/100 seconds i2 INTERVAL DAY TO SECOND := INTERVAL '5 04:03:02.01' DAY TO SECOND;
特定の時間隔値がYEAR TO MONTHであるかDAY TO SECONDであるかも指定できます。たとえば、current_timestamp - current_timestampでは、デフォルトでINTERVAL DAY TO SECOND型の値が生成されます。時間隔の型は、次の形式で指定できます。
日付および時刻型の構文の詳細は、『Oracle Database SQLリファレンス』を参照してください。日付/時刻算術の実行例は、『Oracle Databaseアプリケーション開発者ガイド-基礎編』を参照してください。
PL/SQLコンパイラはコメントを無視しますが、ユーザーはコメントを無視しないでください。プログラムにコメントを付け加えると、わかりやすくなり理解に役立ちます。一般に、コメントは各コード・セグメントの目的や使用方法を説明するために使用します。PL/SQLでは、単一行コメントと複数行コメントの2種類のコメント・スタイルがサポートされています。
単一行コメントは、行の中の任意の位置にある二重ハイフン(--)から始まり、その行の終わりまで続きます。次に例を示します。
DECLARE howmany NUMBER; num_tables NUMBER; BEGIN -- begin processing SELECT COUNT(*) INTO howmany FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables num_tables := howmany; -- Compute some other value END; /
コメントは、行の末尾であれば文の途中でも使用できることに注意してください。
プログラムのテストやデバッグのときに、コード中の1行を無効にする場合があります。次の例では、行をコメントにすることによってその行を無効にする方法を示します。
-- DELETE FROM employees WHERE comm_pct IS NULL;
例2-5に示すように、複数行コメントは、スラッシュ-アスタリスク(/*)で始まってアスタリスク-スラッシュ(*/)で終わり、複数行にまたがることができます。複数行コメントのデリミタを使用すると、コードの一部分をすべてコメントにできます。
DECLARE some_condition BOOLEAN; pi NUMBER := 3.1415926; radius NUMBER := 15; area NUMBER; BEGIN /* Perform some simple tests and assignments */ IF 2 + 2 = 4 THEN some_condition := TRUE; /* We expect this THEN to always be performed */ END IF; /* The following line computes the area of a circle using pi, which is the ratio between the circumference and diameter. After the area is computed, the result is displayed. */ area := pi * radius**2; DBMS_OUTPUT.PUT_LINE('The area is: ' || TO_CHAR(area)); END; /
コメントはネストできません。また、Oracleプリコンパイラ・プログラムが処理するPL/SQLブロックの中では、単一行コメントは使用できません。これは、行の終わりを示す文字が無視され、単一行コメントが行の終わりでなくブロックの終わりまで続いてしまうためです。この場合、かわりに/* */表記法を使用します。
プログラムは、変数と定数に値を格納します。プログラムの実行中に、変数の値を変更できますが、定数の値は変更できません。
変数および定数は、任意のPL/SQLブロック、サブプログラムまたはパッケージの宣言部で宣言できます。宣言によって、値の記憶域を割り当て、データ型を指定し、値を参照できるように格納場所の名前を決めます。
次に例を示します。
DECLARE birthday DATE; emp_count SMALLINT := 0;
1つ目の宣言で、DATE型の変数の名前を決めています。2つ目の宣言で、SMALLINT型の変数の名前を決め、代入演算子を使用して変数に初期値0を代入しています。
代入演算子の後に続く式は複雑なものでもかまいません。また、事前に初期化されている変数を参照することもできます。
DECLARE pi REAL := 3.14159; radius REAL := 1; area REAL := pi * radius**2;
変数はデフォルトでNULLに初期化されます。そのため、変数宣言に「:= NULL」を含めると冗長になります。
定数を宣言するには、型指定子の前にキーワードCONSTANTが必要です。次の宣言では、REAL型の定数の名前を決め、定数に変更不可能な値5000を代入しています。定数は、宣言の中で初期化する必要があります。それ以外の場合は、コンパイル・エラーが発生します。
DECLARE credit_limit CONSTANT REAL := 5000.00; max_days_in_year CONSTANT INTEGER := 366; urban_legend CONSTANT BOOLEAN := FALSE;
変数の初期化には、代入演算子のかわりにキーワードDEFAULTも使用できます。次に例を示します。
blood_type CHAR := 'O';
この宣言は、次のように書き換えることができます。
blood_type CHAR DEFAULT 'O';
標準的な値を持つ変数には、DEFAULTを使用します。特殊な値を持つ変数(カウンタやアキュムレータ)には、代入演算子を使用します。次に例を示します。
DEFAULTを使用して、サブプログラム・パラメータ、カーソル・パラメータおよびユーザー定義レコードのフィールドを初期化することもできます。
宣言によって、初期値を代入する以外にNOT NULL制約を付けることもできます。
NOT NULLと定義されている変数にはNULLを代入できません。NULLを代入しようとすると、PL/SQLは事前定義の例外VALUE_ERRORを呼び出します。
NOT NULL制約の後に初期化句を続ける必要があります。
PL/SQLでは、サブタイプNATURALNとPOSITIVENは、あらかじめNOT NULLとして定義されています。これらの型の変数を宣言する場合は、NOT NULL制約を省略できますが、初期化句を含める必要があります。
%TYPE属性は、変数またはデータベース列のデータ型を与えます。例2-6に示すように、%TYPEで宣言した変数は、変数のデータ型の他にデフォルト値と制約を継承します。
DECLARE credit PLS_INTEGER RANGE 1000..25000; debit credit%TYPE; v_name VARCHAR2(20); name VARCHAR2(20) NOT NULL := 'JoHn SmItH'; -- If we increase the length of NAME, the other variables become longer also upper_name name%TYPE := UPPER(name); lower_name name%TYPE := LOWER(name); init_name name%TYPE := INITCAP(name); BEGIN -- display inherited default values DBMS_OUTPUT.PUT_LINE('name: ' || name || ' upper_name: ' || upper_name || ' lower_name: ' || lower_name || ' init_name: ' || init_name); -- lower_name := 'jonathan henry smithson'; invalid, character string is too long -- lower_name := NULL; invalid, NOT NULL CONSTRAINT -- debit := 50000; invalid, value out of range END; /
%TYPE属性を使用して宣言された変数は、データ型指定子を使用して宣言された変数と同じように扱われます。たとえば前述の宣言では、PL/SQLはdebitをPLS_INTEGER型の変数として扱います。%TYPE属性を使用した宣言には、初期化句も含めることができます。
%TYPE属性は、データベース列を参照する変数を宣言する場合に特に便利です。次の例のように、表や列を参照したり、所有者、表、列を参照することができます。
DECLARE -- If the length of the column ever changes, this code -- will use the new length automatically. the_trigger user_triggers.trigger_name%TYPE;
table_name.column_name.%TYPEを使用して変数を宣言する場合、実際のデータ型、および精度、位取り、長さなどの属性を知っておく必要はありません。列のデータベース定義が変更された場合でも、変数のデータ型は実行時にそれに対応して変更されます。ただし、%TYPE変数はNOT NULL、チェック制約またはデフォルト値などの列制約を継承しません。たとえば、例2-7で、データベース列empidがNOT NULLとして定義されていても、変数v_empidにNULLを代入できます。
CREATE TABLE employees_temp (empid NUMBER(6) NOT NULL PRIMARY KEY, deptid NUMBER(6) CONSTRAINT check_deptid CHECK (deptid BETWEEN 100 AND 200), deptname VARCHAR2(30) DEFAULT 'Sales'); DECLARE v_empid employees_temp.empid%TYPE; v_deptid employees_temp.deptid%TYPE; v_deptname employees_temp.deptname%TYPE; BEGIN v_empid := NULL; -- this works, null constraint is not inherited -- v_empid := 10000002; -- invalid, number precision too large v_deptid := 50; -- this works, check constraint is not inherited -- the default value is not inherited in the following DBMS_OUTPUT.PUT_LINE('v_deptname: ' || v_deptname); END; /
%TYPEを使用して宣言したサブタイプによって継承される列制約の詳細は、「サブタイプの制約およびデフォルト値」を参照してください。
%ROWTYPE属性は、表またはビューの中の行を表すレコード型を与えます。行の中の列と、それに対応するレコード中のフィールドは、同じ名前と同じデータ型を持ちます。ただし、例2-8に示すように、%ROWTYPEレコードのフィールドはNOT NULL、チェック制約またはデフォルト値などの制約を継承しません。例3-11を参照してください。
DECLARE emprec employees_temp%ROWTYPE; BEGIN emprec.empid := NULL; -- this works, null constraint is not inherited -- emprec.empid := 10000002; -- invalid, number precision too large emprec.deptid := 50; -- this works, check constraint is not inherited -- the default value is not inherited in the following DBMS_OUTPUT.PUT_LINE('emprec.deptname: ' || emprec.deptname); END; /
例2-9に示すように、レコードには、表から選択された行全体のデータを格納することも、カーソルまたは強い型指定のカーソル変数でフェッチされた行全体のデータを格納することもできます。
DECLARE -- %ROWTYPE can include all the columns in a table... emp_rec employees%ROWTYPE; -- ...or a subset of the columns, based on a cursor. CURSOR c1 IS SELECT department_id, department_name FROM departments; dept_rec c1%ROWTYPE; -- Could even make a %ROWTYPE with columns from multiple tables. CURSOR c2 IS SELECT employee_id, email, employees.manager_id, location_id FROM employees, departments WHERE employees.department_id = departments.department_id; join_rec c2%ROWTYPE; BEGIN -- We know EMP_REC can hold a row from the EMPLOYEES table. SELECT * INTO emp_rec FROM employees WHERE ROWNUM < 2; -- We can refer to the fields of EMP_REC using column names -- from the EMPLOYEES table. IF emp_rec.department_id = 20 AND emp_rec.last_name = 'JOHNSON' THEN emp_rec.salary := emp_rec.salary * 1.15; END IF; END; /
%ROWTYPE宣言に初期化句を含めることはできませんが、レコード中のすべてのフィールドに一度に値を代入する方法があります。レコードの宣言で同じ表またはカーソルが参照されている場合は、あるレコードを別のレコードに代入できます。例2-10に、可能なレコードの代入を示します。
DECLARE dept_rec1 departments%ROWTYPE; dept_rec2 departments%ROWTYPE; CURSOR c1 IS SELECT department_id, location_id FROM departments; dept_rec3 c1%ROWTYPE; BEGIN dept_rec1 := dept_rec2; -- allowed -- dept_rec2 refers to a table, dept_rec3 refers to a cursor -- dept_rec2 := dept_rec3; -- not allowed END; /
次の例に示すように、SELECT文またはFETCH文を使用して列の値のリストをレコードに代入できます。列名の順番は、CREATE TABLE文またはCREATE VIEW文で定義された順番である必要があります。
DECLARE dept_rec departments%ROWTYPE; BEGIN SELECT * INTO dept_rec FROM departments WHERE department_id = 30 and ROWNUM < 2; END; /
ただし、レコード型のコンストラクタが存在しない場合は、代入文を使用して列の値のリストをレコードに代入できません。
%ROWTYPE属性と関連のあるカーソルからフェッチされた選択リスト項目は、単純名を持つ必要があります。また、選択リスト項目が式の場合は別名を持つ必要があります。例2-11では、complete_nameという別名を使用して2つの列の連結を表しています。
BEGIN -- We assign an alias (complete_name) to the expression value, because -- it has no column name. FOR item IN ( SELECT first_name || ' ' || last_name complete_name FROM employees WHERE ROWNUM < 11 ) LOOP -- Now we can refer to the field in the record using this alias. DBMS_OUTPUT.PUT_LINE('Employee name: ' || item.complete_name); END LOOP; END; /
PL/SQLでは前方参照ができません。宣言文などの他の文で変数または定数を参照するときは、事前に宣言する必要があります。
PL/SQLではサブプログラムの前方宣言が可能です。詳細は、「ネストしたPL/SQLサブプログラムの宣言」を参照してください。
言語によっては、同一のデータ型の複数の変数の並びを一度に宣言できます。ただし、PL/SQLではそれができません。各変数を次のように別々に宣言する必要があります。
DECLARE -- Multiple declarations not allowed. -- i, j, k, l SMALLINT; -- Instead, declare each separately. i SMALLINT; j SMALLINT; -- To save space, you can declare more than one on a line. k SMALLINT; l SMALLINT;
定数、変数、カーソル、カーソル変数、例外、プロシージャ、ファンクション、パッケージなどのPL/SQLプログラム項目には、いずれも同じネーミング規則が適用されます。名前には単純名、修飾名、リモート名または修飾リモート名があります。たとえば、プロシージャ名raise_salaryは次のように使用できます。
raise_salary(...); -- simple
emp_actions.raise_salary(...); -- qualified
raise_salary@newyork(...); -- remote
emp_actions.raise_salary@newyork(...); -- qualified and remote
1番目の例ではプロシージャ名をそのまま使用しています。2番目の例では、プロシージャがemp_actionsという名前のパッケージに格納されているため、ドット表記法を使用して名前を修飾する必要があります。3番目の例では、プロシージャがリモート・データベースに格納されているため、リモート・アクセスのインジケータ(@)を使用してデータベース・リンクnewyorkを参照しています。4番目の例では、プロシージャ名を修飾し、データベース・リンクの参照も行っています。
シノニムを作成し、表、順序、ビュー、スタンドアロン・サブプログラム、パッケージ、オブジェクト型などのリモート・スキーマ・オブジェクトに関する位置の透過性を提供できます。ただし、サブプログラムやパッケージの中で宣言された項目については、シノニムを作成できません。これには、定数、変数、カーソル、カーソル変数、例外およびパッケージ化されたサブプログラムが該当します。
同じ有効範囲の中では、宣言されたすべての識別子が他と重複しないものである必要があります。そのため、変数と定数はデータ型が異なる場合でも同じ名前を共有できません。例2-12では、2番目の宣言は誤りです。
DECLARE valid_id BOOLEAN; valid_id VARCHAR2(5); -- not allowed, duplicate identifier BEGIN -- The error occurs when the identifier is referenced, -- not in the declaration part. valid_id := FALSE; -- raises an error here END; /
識別子に適用される有効範囲規則については、「PL/SQLの識別子の有効範囲と可視性」を参照してください。
定数、変数およびパラメータの名前では、すべての識別子と同様に大/小文字が区別されません。たとえば、PL/SQLは次の名前を同じものとみなします。
DECLARE zip_code INTEGER; Zip_Code INTEGER; -- duplicate identifier, despite Z/z case difference BEGIN zip_code := 90120; -- raises error here because of duplicate identifiers END; /
潜在的にあいまいなSQL文では、データベース列の名前はローカル変数名および仮パラメータ名より優先されます。たとえば、同じ名前の変数と列の両方が1つのWHERE句で使用された場合、SQLは両方とも列を参照するとみなします。
例2-14に示すように、重複を避けるため、ローカル変数と仮パラメータの名前に接頭辞を追加するか、ブロック・ラベルを使用して参照を修飾します。
CREATE TABLE employees2 AS SELECT last_name FROM employees; <<main>> DECLARE last_name VARCHAR2(10) := 'King'; v_last_name VARCHAR2(10) := 'King'; BEGIN -- deletes everyone, because both LAST_NAMEs refer to the column DELETE FROM employees2 WHERE last_name = last_name; DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; -- OK, column and variable have different names DELETE FROM employees2 WHERE last_name = v_last_name; DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; -- OK, block name specifies that 2nd last_name is a variable DELETE FROM employees2 WHERE last_name = main.last_name; DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.'); ROLLBACK; END; /
例2-15では、ローカル変数と仮パラメータへの参照を、サブプログラム名を使用して修飾しています。
DECLARE FUNCTION dept_name (department_id IN NUMBER) RETURN departments.department_name%TYPE IS department_name departments.department_name%TYPE; BEGIN -- DEPT_NAME.department_name specifies the local variable -- instead of the table column SELECT department_name INTO dept_name.department_name FROM departments WHERE department_id = dept_name.department_id; RETURN department_name; END; BEGIN FOR item IN (SELECT department_id FROM departments) LOOP DBMS_OUTPUT.PUT_LINE('Department: ' || dept_name(item.department_id)); END LOOP; END; /
名前解決の詳細は、付録B「PL/SQLでの識別子名の解決」を参照してください。
識別子に対する参照は、その有効範囲と可視性に従って解決されます。識別子の有効範囲とは、その識別子の参照が可能な、プログラム・ユニット(ブロック、サブプログラムまたはパッケージ)の領域です。識別子は、未修飾の名前で識別子を参照できる領域からのみ、可視の状態になっています。図2-1は、xという名前の変数の有効範囲と可視性を示します。この変数は囲みブロックで宣言されてからサブブロックで再宣言されます。
あるPL/SQLブロックで宣言された識別子は、そのブロックに対してはローカルであり、そのサブブロックすべてに対してはグローバルです。グローバル識別子がサブブロックの中で再宣言されると、両方の識別子が有効範囲内にあることになります。ただし、サブブロックの中でグローバル識別子を参照する場合は修飾名が必要になるため、可視であるのはローカル識別子のみです。
同じブロックで識別子を2度宣言できませんが、同じ識別子を2つの異なるブロックで宣言できます。識別子が表す2つの項目は区別され、一方を変更しても他方には影響がありません。ただし、あるブロックから、同じレベルの他のブロックで宣言されている識別子への参照はできません。そのような識別子は、そのブロックに対してローカルでもグローバルでもないためです。
例2-16に、有効範囲規則を示します。あるサブブロックで宣言された識別子は、別のサブブロックで参照できないことに注意してください。これは、あるブロックと同じレベルでネストされた他のブロックで宣言された識別子を、そのブロックで参照できないためです。
DECLARE a CHAR; b REAL; BEGIN -- identifiers available here: a (CHAR), b DECLARE a INTEGER; c REAL; BEGIN NULL; -- identifiers available here: a (INTEGER), b, c END; DECLARE d REAL; BEGIN NULL; -- identifiers available here: a (CHAR), b, d END; -- identifiers available here: a (CHAR), b END; /
グローバル識別子はサブブロックで再宣言でき、その場合はローカルな宣言が優先され、サブブロックでは、修飾名を使用しないとグローバル識別子を参照できません。例2-17に示すように、外側のブロックのラベルを修飾子として使用できます。
<<outer>> DECLARE birthdate DATE := '09-AUG-70'; BEGIN DECLARE birthdate DATE; BEGIN birthdate := '29-SEP-70'; IF birthdate = outer.birthdate THEN DBMS_OUTPUT.PUT_LINE ('Same Birthday'); ELSE DBMS_OUTPUT.PUT_LINE ('Different Birthday'); END IF; END; END; /
また、例2-18に示すように、外側のサブプログラムの名前を修飾子として使用できます。
CREATE OR REPLACE PROCEDURE check_credit(limit NUMBER) AS rating NUMBER := 3; FUNCTION check_rating RETURN BOOLEAN IS rating NUMBER := 1; over_limit BOOLEAN; BEGIN IF check_credit.rating <= limit THEN over_limit := FALSE; ELSE rating := limit; over_limit := TRUE; END IF; RETURN over_limit; END check_rating; BEGIN IF check_rating THEN DBMS_OUTPUT.PUT_LINE( 'Credit rating over limit (' || TO_CHAR(limit) || ').' || ' Rating: ' || TO_CHAR(rating)); ELSE DBMS_OUTPUT.PUT_LINE( 'Credit rating OK. ' || 'Rating: ' || TO_CHAR(rating) ); END IF; END; / CALL check_credit(1);
ただし、同一の有効範囲内でラベルとサブプログラムを同じ名前にすることはできません。例2-19に示すように、ラベルを重複して使用しないようにしてください。
<<compute_ratio>> <<another_label>> DECLARE numerator NUMBER := 22; denominator NUMBER := 7; the_ratio NUMBER; BEGIN <<inner_label>> <<another_label>> DECLARE denominator NUMBER := 0; BEGIN -- first use the denominator value = 7 from global DECLARE -- to compute a rough value of pi the_ratio := numerator/compute_ratio.denominator; DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio); -- now use the local denominator value = 0 to raise an exception -- inner_label is not needed but used for clarification the_ratio := numerator/inner_label.denominator; DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio); -- if you use a duplicate label, you might get errors -- or unpredictable results the_ratio := numerator/another_label.denominator; DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Divide-by-zero error: can''t divide ' || numerator || ' by ' || denominator); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Unexpected error.'); END inner_label; END compute_ratio; /
変数に値を代入する場合は、代入文を使用します。たとえば、次の文では変数bonusの古い値を上書きして、新しい値を代入します。
bonus := salary * 0.15;
変数と定数は、ブロックまたはサブプログラムに入るたびに初期化されます。デフォルトでは、変数はNULLに初期化されます。例2-20に示すように、変数を明示的に初期化しないかぎり、その値は未定義(NULL)です。
DECLARE counter INTEGER; BEGIN -- COUNTER is initially NULL, so 'COUNTER + 1' is also null. counter := counter + 1; IF counter IS NULL THEN DBMS_OUTPUT.PUT_LINE('COUNTER is NULL not 1.'); END IF; END; /
予期しない結果を避けるため、値を代入する前に変数を参照しないでください。代入演算子の後に続く式は、複雑なものでもかまいませんが、そのデータ型は変数のデータ型と同じか、または変数のデータ型に変換できるものである必要があります。
例2-21に示すように、ブール変数に代入できるのは、値TRUE、FALSEおよびNULLのみです。関係演算子を使用して、これらのリテラル値、または比較などの式を代入できます。
DECLARE done BOOLEAN; -- DONE is initially NULL counter NUMBER := 0; BEGIN done := FALSE; -- Assign a literal value WHILE done != TRUE -- Compare to a literal value LOOP counter := counter + 1; done := (counter > 500); -- If counter > 500, DONE = TRUE END LOOP; END; /
SELECT文を使用しても変数に値を代入できます。例2-22に示すように、選択リストの項目ごとに、対応する型互換の変数がINTOリストに存在している必要があります。
DECLARE emp_id employees.employee_id%TYPE := 100; emp_name employees.last_name%TYPE; wages NUMBER(7,2); BEGIN SELECT last_name, salary + (salary * nvl(commission_pct,0)) INTO emp_name, wages FROM employees WHERE employee_id = emp_id; DBMS_OUTPUT.PUT_LINE('Employee ' || emp_name || ' might make ' || wages); END; /
SQLにはBOOLEAN型がないため、列の値を選択してBOOLEAN変数に代入することはできません。変数の値が未定義の場合を含め、DML文での変数の代入の詳細は、「データ操作」を参照してください。
式はオペランドと演算子を使用して作成します。オペランドとは、変数、定数、リテラルまたはファンクション・コールのことで、式の中の値はオペランドを使用して表現します。単純な算術式の例を次に示します。
-X / 2 + 3
否定演算子(-)のような単項演算子は、1つのオペランドに対して作用します。除算演算子(/)のようなバイナリ演算子は、2つのオペランドに対して作用します。PL/SQLには3項演算子はありません。
最も単純な式は変数1つで構成され、その変数の値が式の値になります。PL/SQLは、演算子が指定する方法でオペランドの値を組み合せて、式を評価します。式は常に1つの値を戻します。PL/SQLは、式の内容と、式が使用されているコンテキストに基づいてこの値のデータ型を決定します。
式の中の演算は、優先順位に応じて特定の順序で実行されます。表2-2に、デフォルトでの演算の順序を上から順に示します。
| 演算子 | 演算 |
|---|---|
|
|
指数 |
|
|
恒等、否定 |
|
|
乗算、除算 |
|
|
加算、減算、連結 |
|
|
比較 |
|
|
論理否定 |
|
|
論理積 |
|
|
論理和 |
優先順位が高い演算子が先に適用されます。たとえば、次の2つの式の結果はどちらも8になります。これは、除算が加算よりも優先順位が高いためです。同じ優先順位の演算子は、特に順序を考慮せずに適用されます。
カッコを使用すると、評価の順序を制御できます。たとえば、次の式ではカッコで演算子のデフォルトの優先順位が上書きされるため、式の結果は11ではなく7になります。
(8 + 6) / 2
次の例では、最も深くネストされた副式が必ず最初に評価されるため、除算の前に減算が実行されます。
100 + (20 / 5 + (7 - 3))
次の例のように、カッコが不要な場合でも、わかりやすくするために自由にカッコを使用できます。
(salary * 0.05) + (commission * 0.25)
論理演算子AND、ORおよびNOTは、表2-3に示す3値論理に従います。ANDとORはバイナリ演算子、NOTは単項演算子です。
真理値表からわかるように、ANDは、オペランドの両方がTRUEの場合にのみTRUEを戻します。一方、ORは、オペランドの片方がTRUEならばTRUEを戻します。NOTはオペランドの反対の値(論理否定)を戻します。たとえば、NOT TRUEはFALSEを戻します。
NOT NULLはNULLを戻します。NULLを伴う式で予測不可能な結果が発生しないように注意してください。「比較文と条件文でのNULLの扱い」を参照してください。
カッコを使用して評価の順序を指定しない場合は、演算子の優先順位によって順序が決定されます。次の式を比べてみてください。
NOT (valid AND done) | NOT valid AND done
ブール変数validとdoneがどちらも値FALSEを持つ場合、1番目の式の結果はTRUEになります。ただし、2番目の式ではNOTがANDより優先されるため、結果はFALSEになります。したがって、2番目の式は次の式と等価になります。
(NOT valid) AND done
次の例では、validの値がFALSEである場合、doneの値とは関係なく式全体の結果がFALSEになることに注意してください。
valid AND done
同様に、次の例では、validの値がTRUEである場合に、doneの値とは関係なく式全体の結果がTRUEになります。
valid OR done
論理式を評価するときに、PL/SQLでは短絡評価を使用します。これによって、PL/SQLは結果が判別できた時点でただちに式の評価を停止します。そのため、評価を続ければエラーになるような式でも書くことができます。例2-23のOR式で考えてみます。
DECLARE on_hand INTEGER := 0; on_order INTEGER := 100; BEGIN -- Does not cause divide-by-zero error; evaluation stops after first expression IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN DBMS_OUTPUT.PUT_LINE('On hand quantity is zero.'); END IF; END; /
on_handの値が0(ゼロ)の場合、左のオペランドはTRUEになるため、PL/SQLは右のオペランドを評価しません。OR演算子を適用する前に両方のオペランドを評価した場合には、右のオペランドは0による除算エラーになります。
短絡評価は、PL/SQLのIF文、CASE文およびCASE式に適用されます。
比較演算子は式と式を比較します。結果は常にTRUE、FALSE、NULLのいずれかです。比較演算子は、一般に、SQL DML文のWHERE句と、条件制御文の中で使用します。例2-24に、異なる型の比較の例を示します。
DECLARE PROCEDURE assert(assertion VARCHAR2, truth BOOLEAN) IS BEGIN IF truth IS NULL THEN DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is unknown (NULL)'); ELSIF truth = TRUE THEN DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is TRUE'); ELSE DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is FALSE'); END IF; END; BEGIN assert('2 + 2 = 4', 2 + 2 = 4); assert('10 > 1', 10 > 1); assert('10 <= 1', 10 <= 1); assert('5 BETWEEN 1 AND 10', 5 BETWEEN 1 AND 10); assert('NULL != 0', NULL != 0); assert('3 IN (1,3,5)', 3 IN (1,3,5)); assert('''A'' < ''Z''', 'A' < 'Z'); assert('''baseball'' LIKE ''%all%''', 'baseball' LIKE '%all%'); assert('''suit'' || ''case'' = ''suitcase''', 'suit' || 'case' = 'suitcase'); END; /
次の表に、関係演算子とその意味を示します。
| 演算子 | 意味 |
|---|---|
|
|
等しい |
|
|
等しくない |
|
|
より小さい |
|
|
より大きい |
|
|
より小さいか、等しい |
|
|
より大きいか、等しい |
IS NULL演算子は、オペランドがNULLの場合はブール値TRUEを、NULLではない場合はFALSEを戻します。NULLが関係する比較は、常に結果がNULLになります。値がNULLかどうかをテストするには、次の文を使用します。
IF variable IS NULL THEN ...
LIKE演算子を使用すると、文字、文字列またはCLOB値をパターンと比較できます。大/小文字が区別されます。LIKEは、パターンが一致すればブール値TRUEを、一致しなければFALSEを戻します。
LIKEを使用してパターンを比較するために、ワイルドカードと呼ばれる2つの特殊な目的の文字を使用できます。アンダースコア(_)は1つの文字を表します。パーセント記号(%)は0(ゼロ)個以上の文字を表します。たとえば、last_nameの値が'JOHNSON'の場合、次の式はTRUEになります。
last_name LIKE 'J%S_N'
パーセント記号やアンダースコアを検索するには、エスケープ文字を定義して、パーセント記号またはアンダースコアの前にそのエスケープ文字を挿入します。次の例では、バックスラッシュをエスケープ文字として使用しているため、文字列中のパーセント記号はワイルドカードとしての役割は果たしません。
IF sale_sign LIKE '50\% off!'ESCAPE '\' THEN...
BETWEEN演算子は、ある値が、指定された範囲に含まれているかどうかをテストします。つまり、「下限以上、上限以下」という意味を持ちます。たとえば、次の式はFALSEです。
45 BETWEEN 38 AND 44
IN演算子は、セット・メンバーシップを調べます。集合のいずれかのメンバーと等しいかどうかがテストされます。集合にはNULLが含まれていてもかまいませんが、NULLは無視されます。たとえば、次の式は、値が集合に含まれるかどうかを調べます。
letter IN ('a','b','c')
この条件を反転する場合は注意が必要です。次の形式の式について考えます。
value NOT IN set
この式では、集合にNULLが含まれているとFALSEになります。
連結演算子(||)は、文字列(CHAR、VARCHAR2、CLOBまたはそれと同等のUnicodeで使用可能な型)を他の文字列に連結します。使用例を次に示します。
'suit' || 'case'
これは、次の行を戻します。
'suitcase'
両方のオペランドがデータ型CHARを持つ場合、連結演算子はCHAR型の値を戻します。一方のオペランドがCLOB値を持つ場合、連結演算子は一時的なCLOBを戻します。それ以外の場合は、VARCHAR2型の値を戻します。
PL/SQLでは、SQL文の中でもプロシージャ文の中でも、変数と定数を比較できます。これらの比較はブール式と呼ばれ、関係演算子で区切られた単純式またはコンポジット式で構成されます。ブール式は一般に論理演算子AND、ORおよびNOTで結合されます。ブール式の結果は常に、TRUE、FALSE、NULLのいずれかになります。
SQL文の中でブール式を使用して、表の中の文が影響を与える列を指定できます。プロシージャ文では、条件制御の基盤としてブール式が使用されます。ブール式には、算術式、文字式および日付式の3種類があります。
関係演算子を使用して数値を比較し、等しいか等しくないかを判定できます。比較は量によるものです。つまり、片方の数値がより大きな量を表す場合、その数値はより大きいとみなされます。たとえば、次のような代入文があるとします。
次の式はTRUEになります。
number1 > number2
文字値を比較して、等しいか等しくないかを判定できます。デフォルトでは、比較は文字列の各バイトのバイナリ値に基づいて行われます。たとえば、次のような代入文があるとします。
次の式はTRUEになります。
string1 > string2
初期化パラメータNLS_COMP=ANSIを設定すると、NLS_SORT初期化パラメータで識別される照合順番を比較に使用できます。照合順番とは、特定の範囲の数値コードが個々の文字に対応しているキャラクタ・セットの内部的な順序のことです。内部的な順番を表す数値が他方の文字より大きい場合、その文字値はより大きいとみなされます。この種の文字が照合順番に使用される場所については、言語ごとに規則が異なる場合があります。たとえば、アクセント記号が付いた文字のソート順序は、バイナリ値が同じであってもデータベース・キャラクタ・セットに応じて異なることがあります。
NLS_SORTパラメータの値によっては、大/小文字およびアクセント記号の有無を区別しない比較を実行できます。大/小文字を区別しない比較では、オペランドの文字の大/小文字が異なる場合でもTRUEが戻されます。アクセント記号の有無を区別しない比較は、大/小文字を区別せず、オペランドのアクセント記号またはデリミタ文字が異なる場合でもTRUEが戻されます。たとえば、大/小文字を区別しない比較では、'True'と'TRUE'の文字値は同じであるとみなされ、'Cooperate'、'Co-Operate'および'coperate'の文字値もすべて同じであるとみなされます。大/小文字を区別せずに比較するには、NLS_SORTパラメータの通常の値の末尾に_CIを付けます。アクセント記号の有無を区別せずに比較するには、NLS_SORTの値の末尾に_AIを付けます。
文字値を比較する場合には、ベース型CHARとVARCHAR2の間にある意味上の違いを考慮する必要があります。詳細は、「CHARとVARCHAR2のデータ型の違い」を参照してください。
多くの型は文字型に変換できます。たとえば、CLOB変数を使用して比較、代入および他の文字操作を実行できます。実行可能な変換の詳細は、「PL/SQLの文字型と文字列型」を参照してください。
日付も比較できます。比較は時系列によってなされます。つまり、片方の日付がより新しければ、その日付はより大きいとみなされます。たとえば、次のような代入文があるとします。
次の式はTRUEになります。
date1 > date2
一般に、実数を比較して等しいかどうかを判定することはお薦めしません。実数は近似値として格納されます。たとえば、次のような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; /
比較する場合は、カッコを使用することをお薦めします。たとえば次の式で、100 < taxはブール値になりますが、これは数値500と比較できないため、この式は無効です。
100 < tax < 500 -- 無効
これをデバッグすれば、次の式になります。
(100 < tax) AND (tax < 500)
ブール変数はそれ自身がTRUEまたはFALSEです。変数をリテラル値のTRUE、FALSEと比較するのではなく、単に変数を条件テストに使用できます。例2-25では、ループはすべて等価です。
DECLARE done BOOLEAN ; BEGIN -- Each WHILE loop is equivalent done := FALSE; WHILE done = FALSE LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT (done = TRUE) LOOP done := TRUE; END LOOP; done := FALSE; WHILE NOT done LOOP done := TRUE; END LOOP; END; /
CLOB値を比較演算子またはLIKEやBETWEENなどのファンクションとともに使用すると、一時的なLOBが作成されます。一時表領域がこのような一時的なLOBを処理できる大きさかどうかを確認する必要があります。
CASE文では、単純な式と検索式の2種類の式が使用されます。これらの式は、その式が使用されるCASE文の種類に対応しています。「CASE文の使用」を参照してください。
単純なCASE式は、1つ以上の選択肢から結果を選択して戻します。CASE式が複数の行にわたるブロックを含む場合でも、CASE式は代入やプロシージャ・コールなどの大きい文の一部を構成する1つの式です。CASE式は選択子を使用します。選択子は、その値によって戻す代替アクションが決まる式です。
CASE式の書式は、例2-26に示すとおりです。選択子(grade)の後に1つ以上のWHEN句があり、各句が順番にチェックされます。選択子の値によって、どの句が評価されるかが決定されます。選択子の値と最初に一致したWHEN句によって結果値が決定され、後続のWHEN句は評価されません。一致する句がない場合は、オプションのELSE句が実行されます。
DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(20); BEGIN appraisal := CASE grade WHEN 'A' THEN 'Excellent' WHEN 'B' THEN 'Very Good' WHEN 'C' THEN 'Good' WHEN 'D' THEN 'Fair' WHEN 'F' THEN 'Poor' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE('Grade ' || grade || ' is ' || appraisal); END; /
オプションのELSE句の機能は、IF文のELSE句に似ています。選択子の値がWHEN句のオプションの1つでなければ、ELSE句が実行されます。ELSE句が指定されておらず、一致するWHEN句がなければ、式はNULLを戻します。
検索CASE式を使用すると、1つの式を様々な値と比較するのではなく、異なる条件をテストできます。この式の書式は、例2-27に示すとおりです。
検索CASE式には選択子はありません。各WHEN句にはブール値を生成する検索条件が含まれており、単一のWHEN句で異なる変数または複数の条件をテストできます。
DECLARE grade CHAR(1) := 'B'; appraisal VARCHAR2(120); id NUMBER := 8429862; attendance NUMBER := 150; min_days CONSTANT NUMBER := 200; FUNCTION attends_this_school(id NUMBER) RETURN BOOLEAN IS BEGIN RETURN TRUE; END; BEGIN appraisal := CASE WHEN attends_this_school(id) = FALSE THEN 'N/A - Student not enrolled' -- Have to test this condition early to detect good students with bad attendance WHEN grade = 'F' OR attendance < min_days THEN 'Poor (poor performance or bad attendance)' WHEN grade = 'A' THEN 'Excellent' WHEN grade = 'B' THEN 'Very Good' WHEN grade = 'C' THEN 'Good' WHEN grade = 'D' THEN 'Fair' ELSE 'No such grade' END; DBMS_OUTPUT.PUT_LINE('Result for student ' || id || ' is ' || appraisal); END; /
検索条件は順番に評価されます。各検索条件のブール値によって、どの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-28では、xとyが等しくないために一連の文が実行されることが予測されます。ただし、NULLは予測不可能です。そのため、xとyが等しいかどうかは不明です。したがって、IF条件はNULLになり、一連の文は実行されずにバイパスされます。
DECLARE x NUMBER := 5; y NUMBER := NULL; BEGIN IF x != y THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('x != y'); -- not executed ELSIF x = y THEN -- also yields NULL DBMS_OUTPUT.PUT_LINE('x = y'); ELSE DBMS_OUTPUT.PUT_LINE('Can''t tell if x and y are equal or not.'); END IF; END; /
次の例では、aとbが等しいために一連の文が実行されると予測されます。ただし、等号条件が成立するかどうかは不明であるため、IF条件はNULLになり、一連の文は実行されずにバイパスされます。
DECLARE a NUMBER := NULL; b NUMBER := NULL; BEGIN IF a = b THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('a = b'); -- not executed ELSIF a != b THEN -- yields NULL, not TRUE DBMS_OUTPUT.PUT_LINE('a != b'); -- not executed ELSE DBMS_OUTPUT.PUT_LINE('Can''t tell if two NULLs are equal'); END IF; END; /
論理演算子NOTをNULL値に適用するとNULLが戻ることに注意してください。このため、次の2つのIF文は必ずしも等価ではありません。
IF x > y THEN high := x; ELSE high := y; END IF;
IF NOT x > y THEN high := y; ELSE high := x; END IF;
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を代入します。
DECLARE null_string VARCHAR2(80) := TO_CHAR(''); address VARCHAR2(80); zip_code VARCHAR2(80) := SUBSTR(address, 25, 0); name VARCHAR2(80); valid BOOLEAN := (name != '');
NULL文字列かどうかをテストする場合は、次のようにIS NULL演算子を使用してください。
IF v_string IS NULL THEN ...
連結演算子はNULLオペランドを無視します。使用例を次に示します。
'apple' || NULL || NULL || 'sauce'
これは、次の行を戻します。
'applesauce'
組込みファンクションに引数NULLが渡されると、次に示す場合を除いてNULLが戻されます。
ファンクションDECODEは、先頭の引数を1つまたは複数の検索式と比較します。検索式は結果式と対になっています。検索式や結果式はNULLの場合があります。検索に成功すると、対応する結果が戻されます。例2-29で、列manager_idがNULLならば、DECODEは値'nobody'を戻します。
DECLARE the_manager VARCHAR2(40); name employees.last_name%TYPE; BEGIN -- NULL is a valid argument to DECODE. In this case, manager_id is null -- and the DECODE function returns 'nobody'. SELECT DECODE(manager_id, NULL, 'nobody', 'somebody'), last_name INTO the_manager, name FROM employees WHERE employee_id = 100; DBMS_OUTPUT.PUT_LINE(name || ' is managed by ' || the_manager); END; /
先頭の引数がNULLの場合、ファンクションNVLは2番目の引数の値を戻します。例2-30では、問合せで指定された列がNULLの場合、ファンクションは値-1を戻し、従業員が存在しないことを出力に示します。
DECLARE the_manager employees.manager_id%TYPE; name employees.last_name%TYPE; BEGIN -- NULL is a valid argument to NVL. In this case, manager_id is null -- and the NVL function returns -1. SELECT NVL(manager_id, -1), last_name INTO the_manager, name FROM employees WHERE employee_id = 100; DBMS_OUTPUT.PUT_LINE(name || ' is managed by employee Id: ' || the_manager); END; /
2番目の引数がNULLの場合、ファンクションREPLACEはオプションの3番目の引数が存在するかどうかにかかわらず、1番目の引数の値を戻します。たとえば、例2-31のREPLACEのコールは、OLD_STRINGの値を変更しません。
DECLARE string_type VARCHAR2(60); old_string string_type%TYPE := 'Apples and oranges'; v_string string_type%TYPE := 'more apples'; -- NULL is a valid argument to REPLACE, but does not match -- anything so no replacement is done. new_string string_type%TYPE := REPLACE(old_string, NULL, v_string); BEGIN DBMS_OUTPUT.PUT_LINE('Old string = ' || old_string); DBMS_OUTPUT.PUT_LINE('New string = ' || new_string); END; /
3番目の引数がNULLならば、REPLACEは、1番目の引数から2番目の引数をすべて削除したものを戻します。たとえば、次のREPLACEのコールは、DASHED_STRINGのダッシュを別の文字で置き換えるのではなく、削除します。
DECLARE string_type VARCHAR2(60); dashed string_type%TYPE := 'Gold-i-locks'; -- When the substitution text for REPLACE is NULL, -- the text being replaced is deleted. name string_type%TYPE := REPLACE(dashed, '-', NULL); BEGIN DBMS_OUTPUT.PUT_LINE('Dashed name = ' || dashed); DBMS_OUTPUT.PUT_LINE('Dashes removed = ' || name); END; /
2番目の引数と3番目の引数がNULLの場合、REPLACEは単に1番目の引数を戻します。
条件付きコンパイルを使用すると、ソース・コードを削除することなく、PL/SQLアプリケーションの機能をカスタマイズできます。たとえば、条件付きコンパイルを使用して、PL/SQLアプリケーションを次のようにカスタマイズできます。
「条件付きコンパイル」の新機能の説明を参照してください。ビジネスユースの事例および実践的な適用事例については、Oracle Technology NetworkのWebサイト(http://www.oracle.com/technology/tech/pl_sql/)を参照してください。
条件付きコンパイルでは、選択ディレクティブ、問合せディレクティブおよびエラー・ディレクティブを使用してコンパイルのソース・テキストを指定します。問合せディレクティブでは、PLSQL_CCFLAGS初期化パラメータの名前/値ペアによって設定された値にアクセスします。選択ディレクティブでは、問合せディレクティブまたは静的パッケージ定数をテストできます。
DBMS_DB_VERSIONパッケージでは、条件付きコンパイルに使用できるデータベースのバージョンおよびリリース定数が提供されます。DBMS_PREPROCESSORパッケージでは、PL/SQLユニットの条件付きコンパイル・ディレクティブによって選択される処理後のソース・テキストにアクセスするためのサブプログラムが提供されます。
条件付きコンパイルのトリガー文字は$で、これによってアプリケーションがコンパイルされる前に処理されるコードが識別されます。条件付きコンパイル制御トークンの形式は次のとおりです。
preprocessor_control_token ::= $plsql_identifier
$は識別子名の先頭に置く必要があり、$と名前の間に空白を入れることはできません。$は識別子名に埋め込むこともできますが、特別な意味は持ちません。予約済のプリプロセッサ制御トークンは、$IF、$THEN、$ELSE、$ELSIF、$ENDおよび$ERRORです。条件付きコンパイル制御トークンの使用例は、例2-34を参照してください。
条件付きコンパイルの選択ディレクティブでは、静的な式を評価して、コンパイルに含める必要があるテキストを判定します。選択ディレクティブの形式は次のとおりです。
$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-33を参照してください。
問合せディレクティブは、コンパイル環境のチェックに使用します。問合せディレクティブの形式は次のとおりです。
inquiry_directive ::= $$id
問合せディレクティブは、「条件付きコンパイルでの事前定義問合せディレクティブの使用」に示すとおり、事前定義またはユーザー定義にできます。次に、条件付きコンパイルが問合せディレクティブを解決しようとする場合の処理フローの順序を示します。
idは、$$idの形式で、問合せディレクティブとして検索キーに使用します。
PLSQL_CCFLAGS初期化パラメータの文字列が右から左へスキャンされ、idで一致名(大/小文字を区別しない)が検索されて、検出されると完了します。
事前定義された問合せディレクティブが検索され、検出されると完了します。
$$idを値に解決できない場合は、ソース・テキストがラップされていなくてもPLW-6003警告メッセージがレポートされます。リテラルNULLは、未定義の問合せディレクティブの値として代入されます。PL/SQLコードがラップされている場合は、未定義の問合せディレクティブが示されないように、警告メッセージが無効になります。
たとえば、次のようなセッション設定があるとします。
$$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-34を参照してください。
この項では、事前定義され、条件式で使用できる問合せディレクティブ名について説明します。このような問合せディレクティブ名には、次のものが含まれます。
PLSQL_CCFLAGS、PLSQL_DEBUG、PLSQL_OPTIMIZE_LEVEL、PLSQL_CODE_TYPE、PLSQL_WARNINGS、NLS_LENGTH_SEMANTICSなどのPL/SQLコンパイル用のOracle初期化パラメータ。「PL/SQLコンパイル用の初期化パラメータ」を参照してください。例については、例2-34を参照してください。SQLのALTER文のREUSE SETTINGS句を使用してPL/SQLユニットを再コンパイルすると、現行のPL/SQLコンパイル環境の初期化パラメータ値が変更されないようにすることができます。例2-35を参照してください。
PLS_INTEGERリテラル値であるPLSQL_LINEは、現行ユニットの$$PLSQL_LINEを参照します。次に例を示します。$IF $$PLSQL_LINE = 32 $THEN ...
PLSQL_LINEの値は、PLSQL_CCFLAGSで明示的に定義できます。
VARCHAR2リテラル値であるPLSQL_UNITは、現行のソース・ユニットを示しています。名前付きコンパイル・ユニットの場合は、$$PLSQL_UNITにユニット名が含まれますが、ユニット名に限定されない場合があります。無名ブロックの場合は、$$PLSQL_UNITに空の文字列が含まれます。次に例を示します。IF $$PLSQL_UNIT = 'AWARD_BONUS' THEN ...
PLSQL_UNITの値は、PLSQL_CCFLAGSで明示的に定義できます。また、前述の例は、通常のPL/SQLのPLSQL_UNITの使用を示しています。$$PLSQL_UNIT = 'AWARD_BONUS'は静的な式ではなくVARCHAR2の比較であるため、$IFでサポートされません。PLSQL_UNITでの$IFの有効な使用の1つは、無名ブロックを決定することです。
$IF $$PLSQL_UNIT IS NULL $THEN ...
条件付きコンパイルの処理では、コンパイラで完全に評価できる静的な式のみが使用できます。変数への参照を含むすべての式またはPL/SQLの実行が必要なファンクションは、コンパイル中には使用できず、評価されません。PL/SQLのデータ型の詳細は、「事前定義されたPL/SQLデータ型の概要」を参照してください。
静的な式とは、静的なBOOLEAN、PLS_INTEGERまたはVARCHAR2式のいずれかです。パッケージで宣言される静的定数も静的な式です。
静的なBOOLEAN式には次のものが含まれます。
TRUE、FALSEおよびリテラルNULL
> 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とyは静的なBOOLEAN式です。
IS NULLおよびx IS NOT NULL。xは静的な式です。
静的なPLS_INTEGER式には次のものが含まれます。
静的なVARCHAR2式には次のものが含まれます。
'abcdef'および'abc' || 'def'
NULL
TO_CHAR(x)。xは静的なPLS_INTEGER式です。
TO_CHAR(x f, n)。xは静的なPLS_INTEGER式で、fとnは静的なVARCHAR2式です。
VARCHAR2式または静的なPLS_INTEGER式です。
静的定数は次のパッケージ仕様部で宣言されます。
static_constant CONSTANT datatype := static_expression;
有効な静的定数の宣言は、次のとおりです。
datatypeとstatic_expressionの型が同じ場合
static_expressionが静的な式である場合
datatypeがBOOLEANまたはPLS_INTEGERのいずれかである場合
静的定数はパッケージ仕様部で宣言する必要があり、package_nameパッケージ本体内にある場合でも、package_name.constant_nameとして参照する必要があります。
静的パッケージ定数が、PL/SQLユニットで有効な選択ディレクティブのBOOLEAN式として使用されると、条件付きコンパイルのメカニズムによって、参照されるパッケージへの依存性が自動的に生成されます。パッケージが変更されると依存ユニットは無効になり、再コンパイルして変更を取得する必要があります。依存性を生成できるのは、有効な静的な式のみです。
複数のPL/SQLユニットの条件付きコンパイルを制御する静的定数を持つパッケージを使用する場合は、パッケージ仕様部のみを作成し、複数の依存性のために、そのパッケージ仕様部を条件付きコンパイルの制御専用にします。個々のユニットの条件付きコンパイルを制御するには、PLSQL_CCFLAGSに特定のフラグを設定できます。
例2-32では、my_debugパッケージは、デバッグを制御し、複数のPL/SQLユニットをトレースするための定数を定義します。この例では、定数debugおよびtraceはプロシージャmy_proc1およびmy_proc2の静的な式で使用され、プロシージャからの依存性をmy_debugに生成します。
CREATE PACKAGE my_debug IS debug CONSTANT BOOLEAN := TRUE; trace CONSTANT BOOLEAN := TRUE; END my_debug; / CREATE PROCEDURE my_proc1 IS BEGIN $IF my_debug.debug $THEN DBMS_OUTPUT.put_line('Debugging ON'); $ELSE DBMS_OUTPUT.put_line('Debugging OFF'); $END END my_proc1; / CREATE PROCEDURE my_proc2 IS BEGIN $IF my_debug.trace $THEN DBMS_OUTPUT.put_line('Tracing ON'); $ELSE DBMS_OUTPUT.put_line('Tracing OFF'); $END END my_proc2; /
定数の値の1つを変更すると、パッケージのすべての依存ユニットが新しい値で再コンパイルされます。たとえば、debugの値をFALSEに変更すると、my_proc1がデバッグ・コードなしで再コンパイルされます。my_proc2も再コンパイルされますが、traceの値が変更されていないため、my_proc2は変更されません。
動的PLSQL_CCFLAGS初期化パラメータに、関連した値を持つフラグ名を設定し、PL/SQLユニットの条件付きコンパイルを制御することができます。たとえば、例2-34に示すように、PLSQL_CCFLAGS初期化パラメータをALTER SESSIONで動的に設定し、PL/SQLユニットのデバッグ機能とトレース機能を有効にできます。
また、例2-35に示すように、SQLのALTER PROCEDURE文を使用して、特定のPL/SQLユニットの条件付きコンパイルを独立して制御するように、PLSQL_CCFLAGS初期化パラメータを設定することもできます。
フラグ名は、予約語やキーワードなどの、引用されていない任意のPL/SQL識別子に設定できます。フラグ値を明示的に設定する場合は、TRUE、FALSE、PLS_INTEGERまたはNULLに設定する必要があります。フラグ名およびフラグ値では大/小文字が区別されません。制限を含むPLSQL_CCFLAGS初期化パラメータの詳細は、『Oracle Databaseリファレンス』を参照してください。
DBMS_DB_VERSIONパッケージは、条件付きコンパイルの単純な選択を行う場合に役立つ定数を提供します。PLS_INTEGER定数VERSIONおよびRELEASEは、現行のOracleバージョンとリリース番号を識別します。BOOLEAN定数VER_LE_9、VER_LE_9_1、VER_LE_9_2、VER_LE_10、VER_LE_10_1およびVER_LE_10_2は、そのバージョンおよびリリース以下であることを基準にして、TRUEまたはFALSEに評価されます。たとえば、Oracle 10g リリース2(10.2)の定数は、次のように評価されます。
VER_LE_10は、データベースのバージョンが10以下の状態を表します。この場合、VER_LE_10はTRUEです。
VER_LE_10_2は、データベースのバージョンが10以下で、リリースが2以下の状態を表します。この場合、VER_LE_10_2はTRUEです。
FALSEになります。
例2-33に、条件付きコンパイルでのDBMS_DB_VERSION定数の使用例を示します。Oracleデータベースのバージョンとリリースの両方がチェックされます。ここでは、$ERRORの使用例も示します。
BEGIN $IF DBMS_DB_VERSION.VER_LE_10_1 $THEN $ERROR 'unsupported database release' $END $ELSE DBMS_OUTPUT.PUT_LINE ('Release ' || DBMS_DB_VERSION.VERSION || '.' || DBMS_DB_VERSION.RELEASE || ' is supported.'); -- Note that this COMMIT syntax is newly supported in 10.2 COMMIT WRITE IMMEDIATE NOWAIT; $END END; /
DBMS_DB_VERSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
この項では、条件付きコンパイルの使用例を示します。
例2-34では、BINARY_DOUBLEデータ型をデータベースのPL/SQLユニットの計算で使用できるかどうかを、条件付きコンパイルを使用して判断します。BINARY_DOUBLEデータ型は、10g 以上のデータベースのバージョンでのみ使用できます。ここでは、PLSQL_CCFLAGSパラメータの使用例も示します。
-- set flags for displaying debugging code and tracing info ALTER SESSION SET PLSQL_CCFLAGS = 'my_debug:FALSE, my_tracing:FALSE'; CREATE PACKAGE my_pkg AS SUBTYPE my_real IS $IF DBMS_DB_VERSION.VERSION < 10 $THEN NUMBER; -- check database version $ELSE BINARY_DOUBLE; $END my_pi my_real; my_e my_real; END my_pkg; / CREATE PACKAGE BODY my_pkg AS BEGIN -- set up values for future calculations based on DB version $IF DBMS_DB_VERSION.VERSION < 10 $THEN my_pi := 3.14016408289008292431940027343666863227; my_e := 2.71828182845904523536028747135266249775; $ELSE my_pi := 3.14016408289008292431940027343666863227d; my_e := 2.71828182845904523536028747135266249775d; $END END my_pkg; / CREATE PROCEDURE circle_area(radius my_pkg.my_real) IS my_area my_pkg.my_real; my_datatype VARCHAR2(30); BEGIN my_area := my_pkg.my_pi * radius; DBMS_OUTPUT.PUT_LINE('Radius: ' || TO_CHAR(radius) || ' Area: ' || TO_CHAR(my_area) ); $IF $$my_debug $THEN -- if my_debug is TRUE, run some debugging code SELECT DATA_TYPE INTO my_datatype FROM USER_ARGUMENTS WHERE OBJECT_NAME = 'CIRCLE_AREA' AND ARGUMENT_NAME = 'RADIUS'; DBMS_OUTPUT.PUT_LINE('Datatype of the RADIUS argument is: ' || my_datatype); $END END; /
my_debugにTRUEを設定する場合は、例2-35に示すように、REUSE SETTINGS句があるプロシージャcircle_areaに対してのみこの変更を実行できます。
ALTER PROCEDURE circle_area COMPILE PLSQL_CCFLAGS = 'my_debug:TRUE' REUSE SETTINGS;
DBMS_PREPROCESSORサブプログラムは、条件付きコンパイル・ディレクティブの処理後に、PL/SQLユニットの処理後のソース・テキストを印刷または取り出します。この処理後のテキストは、有効なPL/SQLユニットのコンパイルに使用する実際のソースです。例2-36に、PRINT_POST_PROCESSED_SOURCEプロシージャで例2-34のmy_pkgの処理後の形式を印刷する方法を示します。
CALL DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE('PACKAGE', 'HR', 'MY_PKG');
例2-34のmy_pkgがHRアカウントを使用して10g 以上のリリースのデータベースでコンパイルされる場合、例2-36の出力は次のようになります。
PRINT_POST_PROCESSED_SOURCEは、非選択テキストを空白に置き換えます。処理後のテキストに含まれない例2-34のコードの行は、空白行として表されます。DBMS_PREPROCESSORパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
条件付きコンパイルのディレクティブは、オブジェクト型の仕様部やスキーマ・レベルのネストした表またはVARRAYの仕様部では使用できません。依存する型の属性構造および依存する表の列構造は、オブジェクト型の仕様部で指定された属性構造によって決定されます。オブジェクト型の属性構造に対するすべての変更は、それらの変更が依存オブジェクトに適用されるように、決められた方法で実行される必要があります。変更を適用するには、SQLのALTER TYPE ...ATTRIBUTE文を使用します。プリプロセッサ・ディレクティブを使用すると、ALTER TYPE ...ATTRIBUTE文を使用しなくても、オブジェクト型の属性構造を変更できます。その結果、依存オブジェクトが非同期になったり、依存表がアクセス不可になる場合があります。
SQLパーサーでは、CREATE [OR REPLACE]文や無名ブロックの実行などのSQL操作の実行時に、ディレクティブの配置についての制限があります。これらのSQL操作の実行時、最初の条件付きコンパイル・ディレクティブの位置について、SQLパーサーでは次の制限があります。
IS/ASの直後に配置される場合があります。
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の直後に配置される場合があります。
PL/SQLを使用して、WebアプリケーションやServer Pagesを開発できます。この項では、それらの方法を簡単に説明します。PL/SQLを使用してWebアプリケーションを作成する方法の詳細は、『Oracle Databaseアプリケーション開発者ガイド-基礎編』のPL/SQL Webツールキットを使用したアプリケーションの開発に関する項を参照してください。PL/SQLを使用してWeb Server Pages(PSP)を作成する方法の詳細は、『Oracle Databaseアプリケーション開発者ガイド-基礎編』のPL/SQL Server Pagesの開発に関する項を参照してください。
PL/SQLを使用するとOracleデータベースから直接Webページを生成するアプリケーションを作成できるため、データベースをWeb上で使用可能にし、事務管理部門のデータをイントラネット上でアクセス可能にすることができます。PL/SQL Webアプリケーションのプログラム・フローは、CGI Perlスクリプトのプログラム・フローに似ています。通常、開発者はCGIスクリプトを使用してWebページを動的に作成しますが、多くの場合それらのスクリプトはOracleデータベースへのアクセスに適していません。PL/SQLストアド・プロシージャでWebコンテンツを配信することによって、強力で柔軟なデータベース処理が実現されます。たとえば、DML、動的SQLおよびカーソルを使用できます。各HTTPリクエストを処理する新しいCGIプロセスをforkするためのプロセス・オーバーヘッドを解消することもできます。
PL/SQL GatewayとPL/SQL Web Toolkitを使用して、完全にWebブラウザ・ベースのアプリケーションをPL/SQLに実装できます。
mod_plsqlはOracle HTTP Serverのプラグインであり、WebブラウザでPL/SQLストアド・プロシージャを呼び出せるようにします。
mod_plsqlによってコールされるストアド・プロシージャを使用するための一般的なインタフェースを提供する一連のPL/SQLパッケージです。
PL/SQL Server Pages(PSP)を使用すると、Webページを動的コンテンツで開発できます。これは、Webページ用にHTMLコードを一度に1行ずつ書き出すストアド・プロシージャをコーディングする方法の代替手段です。
特殊なタグを使用すると、PL/SQLスクリプトをHTMLソース・コードに埋め込むことができます。スクリプトは、ページがブラウザなどのWebクライアントによって要求された時に実行されます。スクリプトは、パラメータ、データベースへの問合せまたは更新を受け入れることが可能で、結果を示すカスタマイズ済のページを表示できます。
開発中、PSPはページ・レイアウト用の静的部分およびコンテンツ用の動的部分を持つテンプレートのように動作できます。任意のHTMLオーサリング・ツールを使用してレイアウトを設計できます。プレースホルダは動的コンテンツ用に残します。次に、コンテンツを生成するPL/SQLスクリプトを作成できます。終了した後、作成したPSPファイルをストアド・プロシージャとして単にデータベースにロードします。
PL/SQLには、データを操作するために役立つ多くの強力なファンクションが用意されています。組込みファンクションは、次のカテゴリに分類できます。
表2-4に、各カテゴリのファンクションを示します。エラー・レポート・ファンクションの説明は、「SQLCODEファンクション」および「SQLERRMファンクション」を参照してください。その他のファンクションの説明は、『Oracle Database SQLリファレンス』を参照してください。
SQL文の中では、エラー報告ファンクションSQLCODEとSQLERRMを除くすべてのファンクションを使用できます。また、オブジェクト参照ファンクションDEREF、REFおよびVALUEとファンクションDECODE、DUMPおよびVSIZE以外であれば、すべてのファンクションをプロシージャ文で使用できます。
SQL集計関数(AVGやCOUNTなど)とSQL分析関数(CORRやLAGなど)はPL/SQLに組み込まれていませんが、SQL文に使用できます(ただし、プロシージャ文には使用できません)。
| エラー | 数値 | 文字 | 変換 | 日付 | オブジェクト参照 | その他 |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
![]() Copyright © 2005 Oracle Corporation. All Rights Reserved. |
|