2012-03-30 110 views
3

PostgreSQL文檔手冊http://www.postgresql.org/docs/8.3/interactive/populate.html上的以下鏈接表示要在postgreSQL中禁用自動提交,只需將所有插入語句放在BEGIN中;和COMMIT;在PostgreSQL中填充數據庫

但是,我很難捕捉任何可能發生在BEGIN;承諾;如果發生錯誤(如試圖插入重複的PK),我無法顯式調用ROLLBACK或COMMIT命令。儘管所有插入語句都會自動回滾,但PostgreSQL仍然希望在對COMMIT或ROLLBACK命令進行顯式調用之前可以考慮終止事務。否則,腳本必須等待事務超時並且之後執行的任何語句都會引發錯誤。

在存儲過程中,您可以使用EXCEPTION子句執行此操作,但同樣不適用於執行批量插入的情況。我已經嘗試過了,異常塊沒了我,因爲接下來的statement執行/錯誤發生失敗,錯誤執行後不工作:

ERROR: current transaction is aborted, commands ignored until end of transaction block 

的事務保持打開狀態,因爲它尚未明確敲定調用COMMIT或ROLLBACK;

這裏是我用來測試這個代碼的樣本:

BEGIN; 
    SET search_path TO testing; 
    INSERT INTO friends (id, name) VALUES (1, 'asd'); 
    INSERT INTO friends (id, name) VALUES (2, 'abcd'); 
    INSERT INTO friends (id, nsame) VALUES (2, 'abcd'); /*note the deliberate mistake in attribute name and also the deliberately repeated pk value number 2*/ 
EXCEPTION /* this part does not work for me */ 
    WHEN OTHERS THEN 
     ROLLBACK; 
COMMIT; 

當使用這樣的技術難道我真的要保證所有的語句會成功嗎?這是爲什麼?沒有辦法來捕獲錯誤並顯式調用回滾嗎?

謝謝

回答

2

如果您在開始和提交之間執行操作,那麼在發生異常時,所有內容都會自動回滾。 摘自所發佈的網址: 「在一個事務中進行所有插入操作的另一個好處是,如果插入一行失敗,那麼直到該點插入的所有行的插入都會回滾,所以您贏了不會被部分加載的數據卡住。「

+0

的所有聲明都將回滾,這是正確的;然而,交易不被視爲已完成,並且在此之後計劃執行的任何陳述都不會被執行,因爲上述錯誤在每次提出的新陳述中都會引發; – prince 2012-03-30 15:24:52

+0

你打算完成什麼?如果有其他數據應該被插入而不管前面的失敗如何,您應該將它們添加到不同的begin-commit塊中。 – FooLman 2012-03-30 15:34:22

0

當我初始化數據庫,即創建一系列表/視圖/函數/觸發器/等。和/或加載初始數據,我總是使用psql,並且它是Variables來控制流量。我總是添加:

\set ON_ERROR_STOP 

到我的腳本的頂部,所以無論何時我遇到任何異常,psql都會中止。看起來這也可能有助於你的情況。

而在情況下,當我需要做一些異常處理,我用anonymous code blocks這樣的:

DO $$DECLARE _rec record; 
BEGIN 
FOR _rec IN SELECT * FROM schema WHERE schema_name != 'master' LOOP 
    EXECUTE 'DROP SCHEMA '||_rec.schema_name||' CASCADE'; 
END LOOP; 
EXCEPTION WHEN others THEN 
NULL; 
END;$$; 
DROP SCHEMA master CASCADE;