2015-11-25 21 views
3

我有一個過程,使不同的表更新。如果在程序中的任何地方發生任何錯誤,我希望所有更改都能回滾。因此,我利用這個結構:當發生異常時,讓PL/SQL存儲過程回滾所有更改?

CREATE PROCEDURE foo (x NUMBER) IS 
BEGIN 
    -- Do some inserts here. 
    INSERT INTO bar VALUES (x); 
    -- Sometimes there might be an error. 
    IF x = 3 THEN 
    RAISE_APPLICATION_ERROR(-20000, 'Wooops...'); 
    END IF; 
EXCEPTION 
    WHEN OTHERS THEN 
    --Rollback all the changes and then raise the error again. 
    ROLLBACK; 
    RAISE; 
END foo; 

的問題是,這將回滾已經完成,因爲最後一次提交,而不是由程序所做的更改一切。舉例來說,這將插入4和5,但1和2將被回滾:

BEGIN 
    FOR x IN 1..5 LOOP 
    BEGIN 
     foo(x); 
    EXCEPTION 
     WHEN OTHERS THEN 
     NULL; 
    END; 
    END LOOP; 
END; 

我怎樣才能使程序回滾只有改變這個通話過程中的程序做了?我想我應該使用交易,但我不知道如何設置它。

請注意,我想修復此過程的代碼,而不是在調用它的代碼中。

+2

看到甲骨文保存點http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10001.htm – kevinsky

回答

8

在Oracle中,您可以使用SAVEPOINTS。這將是這樣的:

CREATE PROCEDURE foo (x NUMBER) IS 
BEGIN 
    SAVEPOINT update_bar; 

    -- Do some inserts here. 
    INSERT INTO bar VALUES (x); 
    -- Sometimes there might be an error. 
    IF x = 3 THEN 
    RAISE_APPLICATION_ERROR(-20000, 'Wooops...'); 
    END IF; 
EXCEPTION 
    WHEN OTHERS THEN 
    -- Rollback everything which was made after `SAVEPOINT update_bar` 
    ROLLBACK TO update_bar; 
    RAISE; 
END foo; 
+0

你還需要添加一個COMMIT? – JFPicard

+1

如果你願意承諾是的 –

+0

謝謝你的回答!會有什麼樣的問題,因爲每次調用該過程時都會有一個保存點,而且這個保存點是在同一時間創建的?或者一旦程序完成,Oracle是否忘記了保存點? – Anders