PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

PSQLException:la transazione corrente viene interrotta, i comandi vengono ignorati fino alla fine del blocco della transazione

Ho ricevuto questo errore utilizzando Java e PostgreSQL durante un inserimento su una tabella. Illustrerò come riprodurre questo errore:

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

Riepilogo:

Il motivo per cui ricevi questo errore è perché hai inserito una transazione e una delle tue query SQL non è riuscita e hai inghiottito quell'errore e l'hai ignorato. Ma non era abbastanza, POI hai usato la stessa connessione, usando la STESSA TRANSAZIONE per eseguire un'altra query. L'eccezione viene generata sulla seconda query formata correttamente perché si utilizza una transazione interrotta per eseguire ulteriore lavoro. PostgreSQL per impostazione predefinita ti impedisce di farlo.

Sto usando: 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".

Il mio driver PostgreSQL è: postgresql-9.2-1000.jdbc4.jar

Utilizzo della versione Java: Java 1.7

Ecco l'istruzione table create per illustrare l'eccezione:

CREATE TABLE moobar
(
    myval   INT
);

Il programma Java causa l'errore:

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();
    }   

}

Il codice sopra produce questo output per me:

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

Soluzioni alternative:

Hai alcune opzioni:

  1. La soluzione più semplice:non essere coinvolto in una transazione. Imposta il connection.setAutoCommit(false); a connection.setAutoCommit(true); . Funziona perché quindi l'SQL non riuscito viene semplicemente ignorato come un'istruzione SQL non riuscita. Puoi fallire quanto vuoi con le istruzioni SQL e PostgreSQL non ti fermerà.

  2. Rimani in una transazione, ma quando rilevi che il primo SQL non è riuscito, esegui il rollback/riavvia o il commit/riavvia la transazione. Quindi puoi continuare a non riuscire tutte le query SQL su quella connessione al database che desideri.

  3. Non catturare e ignorare l'eccezione generata quando un'istruzione SQL ha esito negativo. Quindi il programma si fermerà sulla query errata.

  4. Ottieni invece Oracle, Oracle non genera un'eccezione quando fallisci una query su una connessione all'interno di una transazione e continui a utilizzare quella connessione.

In difesa della decisione di PostgreSQL di fare le cose in questo modo... Oracle era rendendoti morbido nel mezzo lasciandoti fare cose stupide e trascurandolo.