Mysql
 sql >> Database >  >> RDS >> Mysql

Java PreparedStatement e SU AGGIORNAMENTO CHIAVE DUPLICATA:come faccio a sapere se la riga è stata inserita o aggiornata?

Considera la seguente tabella di test 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 ;

con i dati di esempio esistenti come segue:

id  name            email
--  --------------  ----------------
 1  Loblaw, Bob     [email protected]
 2  Thompson, Gord  [email protected]

Con l'impostazione di connessione predefinita compensateOnDuplicateKeyUpdateCounts=false (descritto qui ) il seguente codice 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);
}

produce il seguente output della console

executeUpdate returned 1
    => A new row was inserted: id=3

Ora esegui di nuovo lo stesso codice con i valori dei parametri

ps.setString(1, "Loblaw, Robert");
ps.setString(2, "[email protected]");

e l'output della console è

executeUpdate returned 2
    => An existing row was updated: id=1

Questo dimostra che .executeUpdate può davvero restituire 2 se l'indice univoco fa sì che una riga esistente venga aggiornata. Se hai bisogno di ulteriore assistenza con il tuo effettivo codice di test, quindi dovresti modificare la tua domanda per includerla.

Modifica

Ulteriori test rivelano che .executeUpdate restituirà 1 se

  1. il tentativo di INSERT viene interrotto perché risulterebbe in un valore di chiave UNIQUE duplicato, e
  2. le modifiche specificate ON DUPLICATE KEY UPDATE non modificano effettivamente alcun valore nella riga esistente .

Ciò può essere confermato eseguendo il codice di test precedente due volte di seguito con gli stessi identici valori di parametro. Nota che UPDATE ... id = LAST_INSERT_ID(id) "trick" assicura che l'id corretto viene restituito il valore.

Questo probabilmente spiega i risultati del test di OP se l'unico valore inserito fosse il valore della chiave UNIQUE.