Recebi este erro usando Java e PostgreSQL fazendo uma inserção em uma tabela. Vou ilustrar como você pode reproduzir este erro:
org.postgresql.util.PSQLException: ERROR:
current transaction is aborted, commands ignored until end of transaction block
Resumo:
O motivo pelo qual você recebe esse erro é porque você inseriu uma transação e uma de suas consultas SQL falhou, e você engoliu essa falha e a ignorou. Mas isso não foi suficiente, ENTÃO você usou essa mesma conexão, usando a MESMA TRANSAÇÃO para executar outra consulta. A exceção é lançada na segunda consulta corretamente formada porque você está usando uma transação quebrada para fazer trabalho adicional. O PostgreSQL por padrão impede você de fazer isso.
Estou 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".
Meu driver PostgreSQL é:
postgresql-9.2-1000.jdbc4.jar
Usando a versão Java:
Java 1.7
Aqui está a instrução de criação de tabela para ilustrar a exceção:
CREATE TABLE moobar
(
myval INT
);
O programa Java causa o erro:
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();
}
}
O código acima produz esta saída para mim:
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
Soluções alternativas:
Você tem poucas opções:
-
Solução mais simples:não faça uma transação. Defina oconnection.setAutoCommit(false);
paraconnection.setAutoCommit(true);
. Funciona porque o SQL com falha é simplesmente ignorado como uma instrução SQL com falha. Você pode falhar em instruções SQL o quanto quiser e o PostgreSQL não o impedirá.
-
Permaneça em uma transação, mas quando você detectar que o primeiro SQL falhou, faça rollback/re-start ou commit/restart da transação. Em seguida, você pode continuar falhando em quantas consultas SQL nessa conexão de banco de dados desejar.
-
Não capture e ignore a exceção que é lançada quando uma instrução SQL falha. Em seguida, o programa irá parar na consulta malformada.
-
Em vez disso, obtenha o Oracle, o Oracle não lança uma exceção quando você falha em uma consulta em uma conexão dentro de uma transação e continua usando essa conexão.
Em defesa da decisão do PostgreSQL de fazer as coisas desta forma... Oracle foi deixando você mole no meio, deixando você fazer coisas idiotas e ignorando isso.