Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Java PreparedStatement e ON DUPLICATE KEY UPDATE:como sei se a linha foi inserida ou atualizada?


Considere a seguinte tabela de teste do MySQL:
CREATE TABLE `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

com dados de amostra existentes da seguinte forma:
id  name            email
--  --------------  ----------------
 1  Loblaw, Bob     [email protected]
 2  Thompson, Gord  [email protected]

Com a configuração de conexão padrão compensateOnDuplicateKeyUpdateCounts=false (descrito aqui ) o seguinte código Java
PreparedStatement ps = dbConnection.prepareStatement(
        "INSERT INTO customers (name, email) " +
        "VALUES (?, ?) " +
        "ON DUPLICATE KEY UPDATE " +
            "name = VALUES(name), " +
            "id = LAST_INSERT_ID(id)");
ps.setString(1, "McMack, Mike");
ps.setString(2, "[email protected]");
int euReturnValue = ps.executeUpdate();
System.out.printf("executeUpdate returned %d%n", euReturnValue);
Statement s = dbConnection.createStatement();
ResultSet rs = s.executeQuery("SELECT LAST_INSERT_ID() AS n");
rs.next();
int affectedId = rs.getInt(1);
if (euReturnValue == 1) {
    System.out.printf("    => A new row was inserted: id=%d%n", affectedId);
}
else {
    System.out.printf("    => An existing row was updated: id=%d%n", affectedId);
}

produz a seguinte saída de console
executeUpdate returned 1
    => A new row was inserted: id=3

Agora execute o mesmo código novamente com os valores dos parâmetros
ps.setString(1, "Loblaw, Robert");
ps.setString(2, "[email protected]");

e a saída do console é
executeUpdate returned 2
    => An existing row was updated: id=1

Isso demonstra que .executeUpdate realmente pode retornar 2 se o índice exclusivo fizer com que uma linha existente seja atualizada. Se você precisar de mais assistência com seu real código de teste, então você deve editar sua pergunta para incluí-la.

Editar


Testes adicionais revelam que .executeUpdate retornará 1 se
  1. a tentativa de INSERT foi abortada porque resultaria em um valor de chave UNIQUE duplicado, e
  2. as alterações ON DUPLICATE KEY UPDATE especificadas não modificam nenhum valor na linha existente .

Isso pode ser confirmado executando o código de teste acima duas vezes seguidas com os mesmos valores de parâmetro exatos. Observe que o UPDATE ... id = LAST_INSERT_ID(id) "truque" garante que o id correto valor é devolvido.

Isso provavelmente explica os resultados do teste do OP se o único valor inserido for o valor da chave UNIQUE.