SQL プロシージャーの構造
SQL プロシージャーは、いくつかの論理パーツで構成されているので、SQL プロシージャーの開発では、そのようなパーツを構造化フォーマットでインプリメントする必要があります。
そのフォーマットはきわめて単純明快であり、準拠するのも簡単ですが、これは、ルーチンの設計と意味を単純化するためのものです。
SQL プロシージャーの中心は、コンパウンド・ステートメントです。 コンパウンド・ステートメントには、キーワード BEGIN および END が結び付けられています。 このステートメントは、ATOMIC または NOT ATOMIC のどちらでもかまいません。 デフォルトでは、これは NOT ATOMIC です。
label: BEGIN
Variable declarations
Condition declarations
Cursor declarations
Condition handler declarations
Assignment, flow of control, SQL statements and other compound statements
END label
この図は、1 つ以上のオプションのアトミック・コンパウンド・ステートメント (つまりブロック) で SQL プロシージャーを構成することができ、さらに、1 つの SQL プロシージャー内でのそのようなブロックのネストや逐次取り入れが可能なことを示しています。 このようなアトミック・ブロックのいずれでも、オプションの変数、条件、およびハンドラーの宣言に対して規定された順序があります。 それらは、SQL 制御のステートメントおよびその他の SQL ステートメントを使ってインプリメントされている手続き型論理と、カーソル宣言の導入の前に出現しなければなりません。 SQL プロシージャー本体内の一連の SQL ステートメントを使用して、どこでカーソルを宣言してもかまいません。
SQL プロシージャーに含まれている多くの SQL 制御ステートメントの場合と同じように、制御フローを明確にするため、SQL プロシージャーのアトミック・ブロックにもラベルを付けることができます。 そうすれば、変数の参照および制御ステートメントの参照の転送時に、簡単に正確さを極めることができます。
CREATE PROCEDURE DEL_INV_FOR_PROD (IN prod INT, OUT err_buffer VARCHAR(128))
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
DECLARE SQLCODE integer DEFAULT 0;
DECLARE NO_TABLE CONDITION FOR SQLSTATE '42704';
DECLARE cur1 CURSOR WITH RETURN TO CALLER
FOR SELECT * FROM Inv;
A: BEGIN ATOMIC
DECLARE EXIT HANDLER FOR NO_TABLE
BEGIN
SET ERR_BUFFER='Table Inv does not exist';
END;
SET err_buffer = '';
IF (prod < 200)
DELETE FROM Inv WHERE product = prod;
ELSE IF (prod < 400)
UPDATE Inv SET quantity = 0 WHERE product = prod;
ELSE
UPDATE Inv SET quantity = NULL WHERE product = prod;
END IF;
END A;
B: OPEN cur1;
ENDSQL プロシージャー内の NOT ATOMIC コンパウンド・ステートメント
上記の例は、NOT ATOMIC コンパウンド・ステートメントを解説するものであり、SQL プロシージャーで使用されるデフォルトのタイプです。 コンパウンド・ステートメント内で未処理エラー条件が発生した場合、そのエラーより前に完了したどの作業もロールバックされませんが、コミットもされません。 ステートメントのグループをロールバックできるのは、ROLLBACK または ROLLBACK TO SAVEPOINT ステートメントを使用して、作業単位が明示的にロールバックされる場合のみです。 また、必要であれば、COMMIT ステートメントを使用して、正常に完了したステートメントをコミットすることもできます。
CREATE PROCEDURE not_atomic_proc ()
LANGUAGE SQL
SPECIFIC not_atomic_proc
nap: BEGIN NOT ATOMIC
INSERT INTO c1_sched (class_code, day)
VALUES ('R11:TAA', 1);
SIGNAL SQLSTATE '70000';
INSERT INTO c1_sched (class_code, day)
VALUES ('R22:TBB', 1);
END napSIGNAL ステートメントを実行すると、処理されないエラーがこのステートメントで明示的に発行されます。 その後即時にプロシージャーから戻ります。 プロシージャーから戻った後は、エラーが発生したにもかかわらず、最初の INSERT ステートメントは正常に実行を完了し、行を c1_sched 表に挿入し終わっています。 プロシージャーは、行挿入操作をコミットすることもロールバックすることもありません。 その操作は、SQL プロシージャー呼び出しの属する作業単位が完了するまで、その状態のままになります。
SQL プロシージャー内の ATOMIC コンパウンド・ステートメント
名前から連想されるとおり、ATOMIC コンパウンド・ステートメントは、単体の統一体と考えることができます。 その中で何らかの未処理エラー条件が発生した場合、その時点までに実行されたすべてのステートメントも失敗したとみなされて、ロールバックされます。
ATOMIC コンパウンド・ステートメントを他の ATOMIC コンパウンド・ステートメント内にネストすることはできません。
SAVEPOINT ステートメント、COMMIT ステートメント、または ROLLBACK ステートメントを ATOMIC コンパウンド・ステートメント内部から使用することはできません。 これらがサポートされるのは、SQL プロシージャー内の NOT ATOMIC コンパウンド・ステートメントにおいてのみです。
CREATE PROCEDURE atomic_proc ()
LANGUAGE SQL
SPECIFIC atomic_proc
ap: BEGIN ATOMIC
INSERT INTO c1_sched (class_code, day)
VALUES ('R33:TCC', 1);
SIGNAL SQLSTATE '70000';
INSERT INTO c1_sched (class_code, day)
VALUES ('R44:TDD', 1);
END apSIGNAL ステートメントを実行すると、処理されないエラーがこのステートメントで明示的に発行されます。 その後即時にプロシージャーから戻ります。 最初の INSERT ステートメントは、正常に実行が完了したにもかかわらずロールバックされるので、このプロシージャーでは表には何も行が挿入されていないという結果になります。
ラベルおよび SQL プロシージャーのコンパウンド・ステートメント
コンパウンド・ステートメントおよびループを含め、選択によってはラベルを使用して、SQL プロシージャー内の任意の実行可能ステートメントに名前を付けることができます。 他のステートメント内でラベルを参照することで、コンパウンド・ステートメントまたはループ外部に実行の流れをジャンプさせることができ、さらに、コンパウンド・ステートメントまたはループの先頭にジャンプすることもできます。 ラベルを参照できるのは、GOTO、ITERATE、および LEAVE ステートメント内です。
必要があれば、コンパウンド・ステートメントの終わりに、対応するラベルを付けてもかまいません。 終わりのラベルを付ける場合、先頭で使用したものと同じラベルでなければなりません。
どのラベルも、SQL プロシージャー本体内の固有ラベルでなければなりません。
また、ラベルを使用して、ストアード・プロシージャー内の複数のコンパウンド・ステートメントで同名の変数が宣言された場合に、紛らわしさが生じないようにすることができます。 SQL 変数の名前を修飾するのに、ラベルを使用することができます。