一个简单的存储过程,即从t_information表取数据至t_information_back表,并数据取出后删除t_information的数据,ID是主键,原本想有异常后捕获,循环继续,可test下来,捕获异常,循环也终止了,不知何处有不当之处
CREATE OR REPLACE PROCEDURE PRO_Info_BACK IS
BACKTIME VARCHAR(20);
I NUMBER;
CURSOR CUR_Info IS
SELECT * FROM t_information T ;
BEGIN
I := 0;
FOR SOR_Info IN CUR_Info LOOP
BEGIN
SAVEPOINT SP;
I := I + 1;
INSERT INTO t_information_BACK
VALUES
(SOR_Info.ID,
SOR_Info.name,
SOR_Info.code,
SOR_Info.time,
);
DELETE FROM t_information T WHERE T.ID = SOR_Info.ID;
IF I MOD 1000 = 0 THEN
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO SP;
WRITE_ERROR_LOG('PRO_DIALLOST_BACK',
'1',
SQLCODE,
SUBSTR(SQLERRM, 0, 1000));
END;
END LOOP;
COMMIT;
END PRO_Info_BACK;
------解决方案--------------------
结构没问题,是你用错了方法,不要用rollback to,设置个标签,用goto.
------解决方案--------------------
其实,思路有问题,不要靠系统异常来处理错误,严谨的程序应该应该是在游标内部就做好各种异常判断,异常则跳过处理,直接fetch到下一条记录
------解决方案--------------------
估计你的循环终止是 WRITE_ERROR_LOG 又产生了异常吧?
不然循环应该是不会终止的应该
还有 你每次循环都有SAVEPOINT SP;
但是你却是1000条才提交一次,这次数不一致
你应该在保存的时候 标记下次 然后下次循环再设置保存点SAVEPOINT
还有 你这里应该没有必要1000条保存一次 尽早保存可以提高效率
不然oracle 还要帮你维护 以便考虑你之后要回滚
------解决方案--------------------
刚测试了下 设置同一个保存点名称之间 如果中间没有提交 第2个保存点 会自动提交之前的记录
------解决方案--------------------
上条说错了,你的sp 可以重复使用 每次回滚 都只是回滚到最近的一个指定名称的保存点
比如 SAVEPOINT SP;
dml语句1....
SAVEPOINT SP;
dml 语句2。。。
ROLLBACK TO SP;
ROLLBACK TO SP;
第一个回滚语句只回滚dml语句2
第2个回滚语句没有效果 不会回滚dml语句1
如果有这样地方需求 则需要创建不同的 保存点名称了
可以这样理解:当创建一个同样名称的保存点之后, 之前的相同名称的保存点就不再存在,相当于你之前从来没创建过一样