2016-01-15 17 views
0

我想编写一个从两个表中删除数据的存储过程。 如果任一删除操作失败,我想确保没有数据被删除。如何创建和使用Oracle事务

这应该是一个简单的任务,但我从未在Oracle工作过。 我不是如果我应该使用TRY/CATCH,TRANSACTIONS或SAVEPOINTS。

任何指导,将不胜感激。

目前我有:

CREATE OR REPLACE PROCEDURE SP_DELETE_STUFF 
(
    GROUPNAME IN VARCHAR2 
) AS 
BEGIN 

    SAVEPOINT Original_Start; 

    -- First delete all permissions for a given group 
    DELETE FROM my_table_1 
    WHERE group_name = GROUPNAME; 

    -- Second delete the group 
    DELETE FROM my_table_2 
    WHERE group_name = GROUPNAME; 

    EXCEPTION 
    WHEN OTHERS THEN 
    BEGIN 
     ROLLBACK TO SAVEPOINT Original_Start; 
     COMMIT; 
    END; 
    END 
+1

你有正确的想法,但是,我可能不会使用最后的COMMIT。你孤立你的逻辑(好),你已经把自己节省点(OK),并用它适当的(好)......然而,这样做最终的提交,你会从别的地方提交的部分工作也就是说,无论你怎么称呼你的例程......注意,你甚至可能甚至不需要使用保存点(它们很方便,而且基本上已经正确使用它们),但是你可能不需要它们在这里......也简化了事情。 – Ditto

+0

添加到我的上述观点,你可能会得到这样正常不保存点执行以下操作:1)删除初始'SAVEPOINT Original_Start;'2)去除'COMMIT;'3)改变'ROLLBACK TO SAVEPOINT Original_Start;'来只是'ROLLBACK;在'ROLLBACK后';'4)考虑增加'抛出'5)考虑增加'COMMIT;'2号删除后,异常之前(但也许不是,如果这是从其他地方打来电话,要处理由调用者提交) – Ditto

回答

2

如果你的目标只是回滚所做的更改存储过程的一个特定的呼叫做出如果有错误,你会使用一个savepointrollback to savepoint像你在这里做。

我会质疑您在rollback to savepoint之后使用commit。这将提交存储过程的调用者已经启动的事务。当您的程序遇到错误时,您似乎不太可能要提交调用者的更改。所以我希望你想删除commit

与事务范围无关,我也希望您至少需要重新引发您捕获的异常,以便调用者知道发生了故障。我希望你想要类似

EXCEPTION 
    WHEN OTHERS THEN 
    BEGIN 
     ROLLBACK TO SAVEPOINT Original_Start; 
     RAISE; 
    END; 
+0

也许增加一些关于命名'SAVEPOINT'的内容?你想确保你选择一个不太可能被你称之为重复使用的名字。我想,“Original_Start”会有点过于常见,不安全。 –