PLの語法とは、区切り文字、識別子、テキスト、コンパイル指示、コメントを含む最小の独立した構成要素です。
適用対象
この内容はOceanBaseデータベースEnterprise Editionにのみ適用されます。OceanBaseデータベースCommunity EditionはMySQLモードのみを提供します。
区切り文字
区切り文字とは、PLにおいて特別な意味を持つ文字または文字の組み合わせです。区切り文字に他の文字(スペース文字を含む)を埋め込まないでください。
注意
本記事の区切り文字とOBClientの区切り文字は、異なる意味を持ちます。
PLがサポートする区切り文字は以下の表のとおりです:
| 区切り文字 | 意味 |
|---|---|
| + | 加算演算子 |
| := | 赋値演算子 |
| => | 関連演算子 |
| % | プロパティ指示子 |
| ' | 文字列境界符 |
| . | 要素アクセス演算子 |
| || | 接続演算子 |
| / | 除算演算子 |
| ** | 幂演算子 |
| ( | 式またはリストの境界符(開始) |
| ) | 式またはリストの境界符(終了) |
| : | ホスト変数指示子 |
| , | 区切り文字 |
| << | タグ境界符(開始) |
| >> | タグ境界符(終了) |
| /* | 複数行コメント境界符(開始) |
| */ | 複数行コメント境界符(終了) |
| * | 乗算演算子 |
| " | 引き込み符でマークされた境界符 |
| .. | 範囲演算子 |
| = | 関係演算子(等しい) |
| <> | 関係演算子(不等しい) |
| != | 関係演算子(不等しい) |
| ~= | 関係演算子(不等しい) |
| ^= | 関係演算子(不等しい) |
| < | 関係演算子(より小さい) |
| > | 関係演算子(より大きい) |
| <= | 関係演算子(より小さいか等しい) |
| >= | 関係演算子(より大きいか等しい) |
| @ | リモートアクセス指示子 |
| -- | 単一行コメント |
| ; | ステートメント終了符 |
| - | 減算または負の演算子 |
識別子
識別子は、定数、カーソル、例外、キーワード、ラベル、パッケージ、予約語、サブルーチン、型、変数を含むPL要素の名前付けに使用されます。
識別子内の各文字(アルファベットであるかどうかに関係なく)は意味を持ちます。たとえば、識別子 firstname と first_name は異なります。
隣接する識別子を区切るには、1つ以上のスペース文字または句読点を使用する必要があります。
PL識別子は、ダブルクォーテーションマークで囲まれていない限り大文字と小文字を区別しません。たとえば、識別子 firstname、FirstName、FIRSTNAME は同じです。
予約語
PL予約語は特別な意味を持つ識別子です。
予約語を通常のユーザー定義識別子として使用することは推奨されません。PL予約語のリストについては、付録PL予約語を参照してください。
プリコンポジット識別子
プリコンポジット識別子は、プリコンポジットパッケージ STANDARD を使用して宣言されます。
プリコンポジット識別子のリストについては、プログラムパッケージSTANDARDによるPL環境の定義を参照してください。
プリコンポジット識別子をユーザー定義識別子として使用できますが、ローカル宣言はグローバル宣言を上書きするため、この方法は推奨されません。
ユーザー定義識別子
ユーザー定義識別子は、データベース文字セットの文字で構成される通常のまたはインポートされた識別子です。
説明
ユーザー定義識別子は、その意味を直接表現できるようにする必要があります。たとえば、cost_per_employee は文字通りの意味を分析できますが、cpe はそうではありません。
通常のユーザー定義識別子
ユーザーは識別子を定義できます。PLはユーザー定義識別子に対して以下の要件と制限を設けています:
最初の文字はアルファベットでなければなりません。
アルファベット、数字、およびスラッシュ(/)、アスタリスク(*)、アンド(&)、ドル記号($)などを含むことができます。
長さは128文字を超えてはなりません。
PL予約語をPL識別子として使用することはできません。
PL識別子は大文字と小文字を区別しません。
以下のユーザー定義識別子は有効です:
t8
telephone#
credit_limit
FirstName
OceanBase$number
money$$tree
SN##
try_again_
引用符付き識別子
引用符付きのユーザー定義識別子は、ダブルクォーテーションマークで囲まれます。
ダブルクォーテーションマークの間には、データベース文字セット内の任意の文字を使用できますが、ダブルクォーテーションマーク、改行文字、および空文字は除かれます。
以下の引用符付き識別子は有効です:
"X+Y"
"first name"
"on/off switch"
"department(s)"
"*** body info ***"
引用符付きのユーザー定義識別子は大文字と小文字を区別しますが、引用符なしで有効な通常のユーザー定義識別子である場合、その識別子が参照される際にはダブルクォーテーションマークはオプションです。省略された場合、識別子は大文字と小文字を区別しません。
予約語を引用符付きのユーザー定義識別子として使用できますが、これは推奨されません。予約語は有効な通常のユーザー定義識別子ではないため、識別子は常にダブルクォーテーションマークで囲まれ、大文字と小文字を区別する必要があります。
obclient> DECLARE
"HELLO" varchar2(10) := 'hello'; -- HELLOはユーザー定義識別子です
"ALL" varchar2(10) := 'all'; -- ALLは予約語です
BEGIN
DBMS_OUTPUT.Put_Line(Hello); -- ダブルクォーテーションマークを使用しなくてもよく、省略された場合は大文字と小文字を区別しません
DBMS_OUTPUT.Put_Line("ALL"); -- ダブルクォーテーションマークを使用する必要があります
end;
/
出力結果は次のとおりです:
hello
all
テキスト
テキストの値は識別子によって表されることも、他の値から計算されることもありません。
たとえば、119は整数テキストであり、'xyz'は文字テキストですが、1+2はテキストではありません。
PLテキストには、すべてのSQLテキストとBOOLEANテキストが含まれます(SQLには含まれません)。BOOLEANテキストは、事前定義された論理値TRUE、FALSE、またはNULLです。NULLは未知の値を表します。
PL文字テキストを使用する際は、次の点に注意してください:
文字テキストは大文字と小文字を区別します。たとえば、「A」と「a」は異なります。
スペース文字には意味があります。たとえば、'abc'と'a b c'は異なります。
PLには改行文字がなく、「この文字列は次のソースコード行で続きます」という意味で使用されます。次のソースコード行で文字列を続ける場合、その文字列には改行文字を使用する必要があります。連結演算子(||)を使用して改行を回避することもできます。
obclient> BEGIN
DBMS_OUTPUT.PUT_LINE('The string
breaks here.');
DBMS_OUTPUT.PUT_LINE('The string ' ||
'contains no line-break character.');
END;
/
出力結果は次のとおりです:
The string
breaks here.
The string contains no line-break character.
「0」から「9」までの数値は、整数テキストの0から9とは等しくありません。PLはこれらを整数に変換するため、算術式で使用できます。
文字数が0の文字テキストの値は
NULLであり、空文字列と呼ばれます。ただし、このNULL値はBOOLEANのNULL値ではありません。通常の文字テキストは、データベースの文字セットに含まれる文字で構成されます。
国家文字テキストは、国家文字セットに含まれる文字で構成されます。
コンパイル指示
コンパイル指示とは、コンパイラがコンパイル時に処理する指示のことです。
コンパイル指示は、キーワード PRAGMA で始まり、その後にコンパイル指示の名前が続きます。コンパイル指示は宣言内または宣言の前に記述される場合があります。特定のコンパイル指示には追加の制限がある場合もあります。一部のコンパイル指示にはパラメータが含まれており、コンパイラがその名前やパラメータを認識できない場合、そのコンパイル指示は無効になります。
PLがサポートするコンパイル指示の種類は以下のとおりです:
| コンパイル命令 | 意味 |
|---|---|
AUTONOMOUS_TRANSACTION Pragma |
独立したトランザクション内でこの個別のサブルーチンを実行し、他のトランザクションとは相互に独立しており、他のセッションで行われている作業の影響を受けないことを示します。 |
COVERAGE Pragma |
テストカバレッジをテストするために使用され、コンパイラがコードカバレッジ分析を行うよう指示します。 |
EXCEPTION_INIT Pragma |
例外にコードを割り当て、例外をその名前とコードで識別できるようにします。 |
INLINE Pragma |
コンパイラに対し、関数呼び出しを生成する代わりに、呼び出し位置で関数をインライン化するよう指示します。 |
RESTRICT_REFERENCES Pragma |
特定ユニット内のPL/SQLサブルーチンによるテーブル、ビューなどのオブジェクトへの参照を制限します。 |
SERIALLY_REUSABLE Pragma |
パッケージ状態がサーバーの1回の呼び出し期間のみ必要であることを示し、長時間実行されるセッションのメモリオーバーヘッドを削減できます。 |
UDF Pragma |
コンパイラがこのPL/SQLユニットをユーザー定義関数としてコンパイルすることを示します。 |
例
例1:SERIALLY_REUSABLEプラグマを使用した例
CREATE PACKAGE pkg1 IS
PRAGMA SERIALLY_REUSABLE;
num NUMBER := 0;
PROCEDURE init_pkg_state(n NUMBER);
PROCEDURE print_pkg_state;
END pkg1;
/
CREATE PACKAGE BODY pkg1 IS
PRAGMA SERIALLY_REUSABLE;
PROCEDURE init_pkg_state (n NUMBER) IS
BEGIN
pkg1.num := n;
END;
PROCEDURE print_pkg_state IS
BEGIN
dbms_output.put_line('Num: ' || pkg1.num);
END;
END pkg1;
/
DROP PACKAGE pkg1;
例2:AUTONOMOUS_TRANSACTIONプラグマを使用した例
CREATE OR REPLACE PROCEDURE log_error(message VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO error_log (error_message, log_date) VALUES (message, SYSDATE);
COMMIT;
END log_error;
例3:EXCEPTION_INITプラグマを使用した例
DECLARE
deadlock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(DEADLOCK_detected, -60);
BEGIN
-- デッドロック例外を発生させるコード
-- ...
EXCEPTION
WHEN deadlock_detected THEN
DBMS_OUTPUT.PUT_LINE('A deadlock was detected.');
END;
例4:INLINEプラグマを使用した例
CREATE OR REPLACE FUNCTION add_numbers(a NUMBER, b NUMBER) RETURN NUMBER IS
PRAGMA INLINE(add_numbers, 'YES');
BEGIN
RETURN a + b;
END add_numbers;
コメント
コメントの目的は、他のアプリケーション開発者がソーステキストを理解するのを助けることです。PLコンパイラはコメントの内容を無視します。
通常、コメントは各コードセグメントの用途を説明するために使用されます。また、廃止されたり未完成のコードセグメントをコメントに変えて無効化することもできます。
1行コメント
1行コメントは -- で始まり、その行の終わりまで続きます。
テストやデバッグ時に、コメントを使用して1行のコードを無効にすることができます。例えば:
-- INSERT INTO t1 VALUES(1, 1)
複数行コメント
複数行コメントは / * で始まり、* / で終わり、複数の行にまたがることができます。
複数行コメントの境界文字を使用して、コードセグメントを「コメントアウト」することができます。ネストされた複数行コメントを使用しないように注意してください。1つの複数行コメントは別の複数行コメントを含むことはできません。ただし、複数行コメントは1行コメントを含むことができます。
以下の例は構文エラーを引き起こします:
/*
IF 1 + 2 = 3 THEN
some_condition := TRUE;
/* 必須
THEN
ステートメントは常に実行されます*/
END IF;
*/
語法間のスペース文字
語法要素の間にスペース文字を配置することで、ソーステキストをより読みやすくすることができます。
以下の例を参照してください:
obclient> DECLARE
a NUMBER := 5;
b NUMBER := 1;
max NUMBER;
BEGIN
IF a>b THEN max:=a;ELSE max:=b;END IF; -- 構文は正しいものの読みにくい
-- 以下のステートメントの方が読みやすいです:
IF a > b THEN
max:=a;
ELSE
max:=b;
END IF;
END;
/