2012-03-30 112 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;