PL/SQLとは、データベース問い合わせ言語SQLをOracleが独自に拡張したプログラミング言語です。入門者向けに基礎からPL/SQLの書き方を解説します。
PL/SQLブロックは宣言部、実行部および例外処理部に分かれていて、この順序で記述する。このうち、宣言部と例外処理部は省略可能で、実行部は必ず存在しなければならない。
DECLARE
-- 宣言部
BEGIN
-- 実行部
EXCEPTION
-- 例外処理部
END;
宣言部は DECLARE 文から始まり、変数やカーソル、ユーザー定義例外の宣言を行なう。
宣言部で宣言した変数を使ってメッセージを出力するPL/SQLブロックの例を示す。
DECLARE
-- 変数の宣言
msg VARCHAR2(50);
BEGIN
-- 変数に文字列を代入
msg := 'Hello, world!';
-- メッセージの出力
DBMS_OUTPUT.PUT_LINE(msg);
END;
/
宣言部で宣言したプロシージャを呼び出してメッセージを出力するPL/SQLブロックの例を示す。
DECLARE
-- プロシージャの宣言
PROCEDURE hello_world(msg IN VARCHAR2) IS
BEGIN
-- メッセージの出力
DBMS_OUTPUT.PUT_LINE(msg);
END;
BEGIN
-- プロシージャの呼び出し
hello_world('Hello, world!');
END;
/
実行部は BEGIN 文から始まり、PL/SQLステートメントを記述する。
PL/SQLのステートメント(文)はセミコロンで終了する。
メッセージを出力するPL/SQLブロックの例を示す。
BEGIN
-- メッセージの出力
DBMS_OUTPUT.PUT_LINE('hello, world');
END;
/
PL/SQLプログラム中にコメントを入れることができる。コメントとは、ユーザーのためにプログラムの使用方法や注意事項といった注釈を記述することであり、PL/SQLプログラムの実行には何の影響も及ぼさない。
コメントの記述スタイルとして、単一行コメントと複数行コメントの2種類がある。
単一行コメントとは、2つ連続したハイフン(--
)から始まり、その行の末尾で終了するコメントである。行の中の任意の位置からコメントを開始することができる。
BEGIN
-- メッセージの出力
DBMS_OUTPUT.PUT_LINE('Hello, world!');
END;
/
PL/SQLブロックは END 文で終了する。省略できない。
複数行コメントとは、スラッシュとアスタリスク(/*
)から始まり、アスタリスクとスラッシュ(*/
)で終わるコメントである。行の中の任意の位置からコメントを開始することができる。単一行コメントと異なり、複数行に渡ってコメントを記述することができる。
BEGIN
/*
メッセージの出力
*/
DBMS_OUTPUT.PUT_LINE('Hello, world!');
END;
/
既存表の列と同じデータ型または既存変数と同じデータ型として変数を宣言する場合、%TYPE 属性を使用することができる。
表の列と同じデータ型として変数を宣言する構文を次に示す。
変数名 表名.列名%TYPE [ := 初期値] ;
他の変数と同じデータ型として変数を宣言する構文を次に示す。
変数名 変数名%TYPE [ := 初期値] ;
%TYPE属性の使用例を次に示す。
DECLARE
emp1 NUMBER;
emp2 emp1%TYPE;
emp3 employee.deptno%TYPE;
構文はSQLのCASE式と似ているが、PL/SQLのCASE文では、THEN句にPL/SQLのプログラムコードを記述できる点が異なる。
CASE
WHEN 条件式1 THEN
-- 条件式1が真のとき実行するステートメント
WHEN 条件式2 THEN
-- 条件式2が真のとき実行するステートメント
WHEN 条件式n THEN
-- 条件式nが真のとき実行するステートメント
ELSE
-- 条件式1~nがすべて偽のとき実行するステートメント
END CASE;
FOR LOOP文は開始値から終了値までカウンタの値を変えながら処理を繰り返す制御文である。
開始値から終了値までカウンタの値をひとつづつ増やしながら処理を繰り返す。
FOR counter IN start..end LOOP
statements
END LOOP;
開始値から終了値までカウンタの値をひとつづつ減らしながら処理を繰り返す。
FOR counter IN REVERSE end..start LOOP
statements
END LOOP;
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 FOR i IN 1..3 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
1
2
3
SQL>
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 FOR i IN REVERSE 1..3 LOOP
3 DBMS_OUTPUT.PUT_LINE(i);
4 END LOOP;
5 END;
6 /
3
2
1
SQL>
IF condition1 THEN
statement_sequence1
[ELSIF condition2 THEN
statement_sequence2]
[ELSE
statement_sequence3]
END IF;
LOOP と END LOOP で囲まれた一連の文を無条件で繰り返す。
[<<label_name>>]
LOOP
statement_sequence
END LOOP [label_name];
label_name にはラベル(固有のループを識別するための名前)を指定する。
ループを終了するには、EXIT 文を使用する。
EXIT [label_name] [ WHEN condition] ;
label_name には、ループのラベルを指定する。label_name を省略した場合は、1番内側のループを終了する。
condition には、ループを終了する条件式を指定する。
LOOP
IF count < 0 THEN
EXIT;
END IF;
count := count + 1;
EXIT WHEN count > 100;
END LOOP;
PRAGMA AUTONOMOUS_TRANSACTIONとは、自立型トランザクションを設定するPL/SQL文である。 自立型トランザクションを指定したサブプログラムは、サブプログラム呼び出し元のトランザクションとは分離されるため、 サブプログラム内の処理だけを COMMIT又はROLLBACKすることができる。
CREATE OR REPLACE PROCEDURE set_ename(
p_empno IN NUMBER,
p_ename IN VARCHAR2
) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE emp SET emane = p_ename WHERE empno = p_empno;
-- 自立型トランザクションは最後にCOMMIT又はROLLBACKする
-- このプロシージャの処理(UPDATE)のみCOMMITする
COMMIT;
EXCEPTION
WHEN OTHERS THEN
-- 自立型トランザクションは最後にCOMMIT又はROLLBACKする
-- このプロシージャの処理(UPDATE)のみROLLBACKする
ROLLBACK;
END;
/
RETURN 文は、サブプログラムの実行を終了させ、コールした側に制御を戻す。サブプログラムの中に複数の RETURN 文が存在してもよい。
プロシージャは RETURN 文が無くても実行部の最後でサブプログラムを終了して、コールした側に制御が戻る。ファンクションは実行部の最後に至るまでに必ず RETURN 文が必要である。
RETURN 文の構文を次に示す。
プロシージャの処理を終了して、呼び出し元に戻る。
RETURN;
ファンクションを処理を終了して、呼び出し元に戻る。呼び出し元には戻り値を返す。
RETURN expr;
構文はSQLのSELECT文に似ているが、SELECT文の結果を格納する変数をINTO句に指定する点が異なる。
SELECT column INTO variable FROM table [WHERE condition]
PL/SQLでSELECT文を使う例を次に示す。
DECLARE
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno = '1901';
END;
/
WHILE 条件式
LOOP
-- 条件式が真のとき実行するステートメント
END LOOP;
NESTED TABLEを定義する構文を次に示す。
TYPE type_name IS TABLE OF element_type [NOT NULL];
varrayを定義する構文を次に示す。
TYPE type_name IS {VARRAY | VARYING ARRAY} (size_limit) OF element_type [NOT NULL];
type_name collection_name;