データベースに加えられ保留中の変更を取り消すには、ROLLBACK文を使用します。たとえば、表から間違った行を削除するなどのミスを犯した場合、ROLLBACKを使用すれば、元のデータをリストアできます。ROLLBACK文は、ホスト変数の値にも、プログラムのフロー制御にも影響がありません。具体的には、ROLLBACK文により次の処理が実行されます。
カレント・トランザクションで実行されたデータベースの変更を取り消します。
すべてのセーブポイントを消去します。
トランザクションを終了します。
解析ロックを除き、すべての行と表のロックを解除します。
CURRENT OF句で参照されるカーソルをクローズします。MODE={ANSI|ANSI14}の場合は、すべての明示カーソルをクローズします。
MODE={ANSI13|ORACLE}の場合、CURRENT OF句で参照されない明示カーソルは、複数のロールバックにわたりオープン状態のままです。
ROLLBACK文は例外処理の一部であるため、プログラムのメイン・パスではなく、エラー処理ルーチン内に指定する必要があります。次の例では、トランザクションをロールバックして、Oracleとの接続を切断します。
EXEC SQL ROLLBACK WORK RELEASE;
オプションのキーワードWORKを指定すると、ANSI互換になります。RELEASEオプションを指定すると、プログラムで使用されているすべてのリソースが解放され、データベースとの接続が切断されます。
WHENEVER SQLERROR GOTO文からエラー処理ルーチンに分岐するとき、そのルーチンにROLLBACK文が含まれている場合は、ロールバックがエラーで失敗すると、プログラムが無限ループに入るおそれがあります。このような無限ループは、ROLLBACK文の前にWHENEVER SQLERROR CONTINUEを記述することで回避できます。
EXEC SQL WHENEVER SQLERROR GOTO sql_error; FOR EACH new employee display 'Employee number? '; read emp_number; display 'Employee name? '; read emp_name; EXEC SQL INSERT INTO EMP (EMPNO, ENAME) VALUES (:emp_number, :emp_name); ENDFOR; ... sql_error: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK RELEASE; display 'Processing error'; exit program with an error;
Oracleは、SQL文を実行する前に、暗黙的なセーブポイント(ユーザーは操作できません)を設定します。SQL文でエラーが発生すると、Oracleは自動的にその文をロールバックし、該当するエラー・コードをSQLCA内のSQLCODEに戻します。たとえば、INSERT文で一意の索引に重複する値を挿入しようとしてエラーが発生すると、その文はロールバックされます。
失敗したSQL文によって開始された作業のみが失われます。現在のトランザクションでその文の前に行われた作業は保持されます。このため、データ定義文が失敗した場合、それに先行する自動コミットは取り消されません。
SQL文を実行する前に、Oracleではその文を解析する、つまり、その文が構文規則に従っているか、あるいは有効なデータベース・オブジェクトを参照しているかを確認する要があります。SQL文の実行中にエラーが検出されると、ロールバックが発生しますが、解析中にエラーが検出されても、ロールバックは発生しません。
Oracleでは、デッドロックを解消するために、1つのSQL文のみをロールバックすることもできます。関連しているトランザクションの1つにエラーが通知され、そのトランザクション内の現在の文がロールバックされます。