保存点(SAVEPOINT)是事务处理过程中的一个标志,与回滚命令(ROLLBACK)结合使用,次要的用途是允许用户将某一段处理回滚而不必回滚整个事务,这在PL/SQL开发中还是很有用途的。
下面的例子中,把SAVEPOINT标记在INSERT语句之前,如果这条INSERT语句试图将反复的数据保存到EMP表中的话,将触发执行事后定义的DUP_VAL_ON_INDEX例外处理,在这里面的ROLLBACK TO do_insert命令将回滚上面的那条INSERT操作,而不会影响前面的任何操作。
DECLARE
emp_id emp.empno%TYPE;
BEGIN
UPDATE emp SET ... WHERE empno = emp_id;
DELETE FROM emp WHERE ...
...
SAVEPOINT do_insert;
INSERT INTO emp VALUES (emp_id, ...);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO do_insert;
END;
如果你定义了多个savepoint,当你指定回滚到某个savepoint时,那么回滚操作将回滚这个savepoint后面的所有操作(即便后面可能标记了N个savepoint)。例如,在一段处理中
你定义了五个savepoint,从第三个savepoint回滚,后面的第四、第五个标记的操作都将被回滚,如果不使用ROLLBACK TO savepoint_name而使用ROLLBACK,将会滚整个事务处理。
如果你在递归子程序里面定义了一个savepoint, 如果每一个递归层都设置了SAVEPOINT. 此时, 你只能回滚到最近的一个savepoint.
Savepoint的声明可以在同一个事务处理里面反复定义. 它的作用就是把savepoint从上一个位置转移到目前的位置. 因此,执行回滚也只回滚到最近的savepoint.
下面是一个例子:
BEGIN
...
SAVEPOINT my_point;
UPDATE emp SET ... WHERE empno = emp_id;
...
SAVEPOINT my_point; -- move my_point to current point
INSERT INTO emp VALUES (emp_id, ...);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO my_point;
END;
另外,Oracle没有对每个session里面可以使用的savepoint个数做限制.