【问题标题】:Can I ask Postgresql to ignore errors within a transaction我可以要求 Postgresql 忽略事务中的错误吗
【发布时间】:2011-02-14 01:49:55
【问题描述】:

我使用带有 PostGIS 扩展的 Postgresql 进行临时空间分析。我通常在 psql 中手动构建和发出 SQL 查询。我总是将分析会话包装在事务中,因此如果我发出破坏性查询,我可以将其回滚。

但是,当我发出包含错误的查询时,它会取消交易。任何进一步的查询都会引发以下警告:

错误:当前交易是 中止,命令被忽略,直到结束 交易区块

有没有办法可以关闭这种行为?每次我打错字时都回滚事务并重新运行以前的查询是很烦人的。

【问题讨论】:

    标签: database postgresql postgis


    【解决方案1】:

    (更新:不需要手动执行此操作,我在 postgresql 邮件列表中询问,结果证明此行为已通过 psql 客户端中设置的ON_ERROR_ROLLBACK 实现)

    要详细说明 Simon 的答案 (+1) ,在您的场景中,您可以在每个交互式查询之后添加一个保存点,始终使用相同的名称(如果查询成功,它会覆盖前一个)。如果出现错误,您会返回上次保存的内容并从那里继续。

    这种工作模式的一个例子:

    db=# select * from test_gral ;
     i |  t   |  n
    ---+------+------
     1 | text | 10.0
    (1 row)
    
    db=# begin;
    BEGIN
    db=#  insert into test_gral values (2,'xx',20); savepoint sp;
    INSERT 0 1
    SAVEPOINT
    db=#  insert into test_gral values (3,'xx',30); savepoint sp;
    INSERT 0 1
    SAVEPOINT
    db=#  insert into test_gralxx values (4,'xx',40); savepoint sp;
    ERROR:  relation "test_gralxx" does not exist
    LINE 1: insert into test_gralxx values (4,'xx',40);
                        ^
    ERROR:  current transaction is aborted, commands ignored until end of transaction block
    db=# ROLLBACK TO SAVEPOINT sp;
    ROLLBACK
    db=#  insert into test_gral values (4,'xx',40); savepoint sp;
    INSERT 0 1
    SAVEPOINT
    db=# commit;
    COMMIT
    db=# select * from test_gral ;
     i |  t   |  n
    ---+------+------
     1 | text | 10.0
     2 | xx   |   20
     3 | xx   |   30
     4 | xx   |   40
    (4 rows)
    

    【讨论】:

    • ON_ERROR_ROLLBACK 变量完全符合我的要求 :)
    • ON_ERROR_ROLLBACK 看起来像是 psql 客户端的一个特性,而不是 postgres 本身(所以你不能从数据库应用程序中使用它,只能从命令行使用)。
    • @Glyph:是的,这是 psql 的一个功能,它专门面向交互式使用 - 这是 OP 的场景。对我来说,当期望的行为有意义时,我很难想到一个应用场景。
    • @leonbloy 好吧,任何其他交互式 SQL 客户端(即支持 postgresql)。
    【解决方案2】:

    关闭它是不可能的,但是你可以使用不同的东西。有类似保存点的东西:

    http://www.postgresql.org/docs/8.4/interactive/sql-savepoint.html

    这样您就可以将您的事务回滚到某个较早的点,而无需将整个事务变为黑色。

    【讨论】:

      【解决方案3】:

      可以编写一个函数,它接受一个字符串参数 executes 它,并使用 exception 子句以不中止您的事务,但是必须为每个语句调用该函数是一个巨大的痛苦你想执行。

      【讨论】:

        【解决方案4】:

        不,没有办法关闭它。错误会为您隐式中止事务,因此您必须回滚并重试。

        【讨论】:

        • 我也是这么想的,但不是。看我的回答。
        【解决方案5】:

        简单的答案是运行

        my_db=> \set ON_ERROR_ROLLBACK interactive
        

        在交互式会话中。另请参阅其实现者的this blog post

        【讨论】:

          猜你喜欢
          • 2017-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-23
          • 2011-01-09
          • 2014-06-06
          • 2019-03-21
          • 2018-12-26
          相关资源
          最近更新 更多