sql >> データベース >  >> RDS >> PostgreSQL

PSQLException:現在のトランザクションは中止され、トランザクションブロックが終了するまでコマンドは無視されます

    テーブルに挿入を行うJavaとPostgreSQLを使用してこのエラーが発生しました。このエラーを再現する方法を説明します:

    org.postgresql.util.PSQLException: ERROR: 
    current transaction is aborted, commands ignored until end of transaction block
    

    概要:

    このエラーが発生する理由は、トランザクションを入力し、SQLクエリの1つが失敗し、その失敗を食い止めて無視したためです。しかし、それだけでは不十分でした。次に、同じ接続を使用し、同じトランザクションを使用して別のクエリを実行しました。壊れたトランザクションを使用して追加の作業を行っているため、2番目の正しく形成されたクエリで例外がスローされます。 PostgreSQLはデフォルトで、これを実行できなくなります。

    使用しているもの: PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".

    私のPostgreSQLドライバーは次のとおりです: postgresql-9.2-1000.jdbc4.jar

    Javaバージョンの使用: Java 1.7

    例外を説明するためのテーブル作成ステートメントは次のとおりです:

    CREATE TABLE moobar
    (
        myval   INT
    );
    

    Javaプログラムによりエラーが発生します:

    public void postgresql_insert()
    {
        try  
        {
            connection.setAutoCommit(false);  //start of transaction.
            
            Statement statement = connection.createStatement();
            
            System.out.println("start doing statement.execute");
            
            statement.execute(
                    "insert into moobar values(" +
                    "'this SQL statement fails, and it " +
                    "is gobbled up by the catch, okfine'); ");
         
            //The above line throws an exception because we try to cram
            //A string into an Int.  I Expect this, what happens is we gobble 
            //the Exception and ignore it like nothing is wrong.
            //But remember, we are in a TRANSACTION!  so keep reading.
    
            System.out.println("statement.execute done");
            
            statement.close();
            
        }
        catch (SQLException sqle)
        {
            System.out.println("keep on truckin, keep using " +
                    "the last connection because what could go wrong?");
        }
        
        try{
            Statement statement = connection.createStatement();
            
            statement.executeQuery("select * from moobar");
    
            //This SQL is correctly formed, yet it throws the 
            //'transaction is aborted' SQL Exception, why?  Because:
            //A.  you were in a transaction.
            //B.  You ran a SQL statement that failed.
            //C.  You didn't do a rollback or commit on the affected connection.
            
        }
        catch (SQLException sqle)
        {
            sqle.printStackTrace();
        }   
    
    }
    

    上記のコードは私のためにこの出力を生成します:

    start doing statement.execute
    
    keep on truckin, keep using the last connection because what could go wrong?
    
    org.postgresql.util.PSQLException: 
      ERROR: current transaction is aborted, commands ignored until 
      end of transaction block
    

    回避策:

    いくつかのオプションがあります:

    1. 最も簡単な解決策:取引をしないでください。 connection.setAutoCommit(false);を設定します connection.setAutoCommit(true);へ 。失敗したSQLは失敗したSQLステートメントとして無視されるため、これは機能します。必要なSQLステートメントをすべて失敗してもかまいません。PostgreSQLはあなたを止めません。

    2. トランザクションを継続しますが、最初のSQLが失敗したことを検出したら、トランザクションをロールバック/再起動またはコミット/再起動します。その後、そのデータベース接続で必要な数のSQLクエリを失敗し続けることができます。

    3. SQLステートメントが失敗したときにスローされる例外をキャッチして無視しないでください。その後、プログラムは不正な形式のクエリで停止します。

    4. 代わりにOracleを入手してください。トランザクション内の接続でクエリに失敗し、その接続を引き続き使用しても、Oracleは例外をスローしません。

    このように物事を行うというPostgreSQLの決定を擁護するために...Oracleは 真ん中で柔らかくなり、馬鹿げたことをして見落とすことができます。



    1. Oracleインタビューの質問

    2. SQLServerデータベースレプリケーション

    3. MySQLでタスクマネージャのデータベースを設計するためのガイド

    4. OracleのストアドプロシージャからResultSetを返す方法は?