Mysql
 sql >> Base de données >  >> RDS >> Mysql

Java PreparedStatement et ON DUPLICATE KEY UPDATE :comment savoir si la ligne a été insérée ou mise à jour ?

Considérez le tableau de test MySQL suivant :

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 ;

avec des exemples de données existants comme suit :

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

Avec le paramètre de connexion par défaut compensateOnDuplicateKeyUpdateCounts=false (décrit ici ) le code Java suivant

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

produit la sortie de console suivante

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

Maintenant, exécutez à nouveau le même code avec les valeurs des paramètres

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

et la sortie de la console est

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

Cela démontre que .executeUpdate peut vraiment renvoyer 2 si l'index unique entraîne la mise à jour d'une ligne existante. Si vous avez besoin d'aide supplémentaire avec votre réel code de test, vous devez modifier votre question pour l'inclure.

Modifier

Des tests supplémentaires révèlent que .executeUpdate renverra 1 si

  1. la tentative d'INSERT est abandonnée car elle entraînerait une valeur de clé UNIQUE en double, et
  2. les modifications ON DUPLICATE KEY UPDATE spécifiées ne modifient en fait aucune valeur dans la ligne existante .

Cela peut être confirmé en exécutant le code de test ci-dessus deux fois de suite avec exactement les mêmes valeurs de paramètre. Notez que le UPDATE ... id = LAST_INSERT_ID(id) "trick" garantit que le bon id la valeur est renvoyée.

Cela explique probablement les résultats des tests d'OP si la seule valeur insérée était la valeur de clé UNIQUE.