MySQL : résoudre l'erreur INSERT IGNORE vs INSERT ? ON DUPLICATE KEY UPDATE

Si l'on essaie d'insérer dans une base de données un enregistrement avec la même clé primaire qu'un autre enregistrement de la table, on obtient une erreur.

Dans les bases de données, une table contient généralement un champ qui est une clé primaire. Il ne peut pas exister deux enregistrements avec la même valeur pour leur clé primaire. Si l'on essaie d'insérer un enregistrement avec la même clé primaire qu'un autre enregistrement de la table, on obtient une erreur. Dans le système de gestion de base de données MySQL, il existe différentes options pour gérer ces erreurs et éviter l'arrêt d'un script.

La commande INSERT possède différentes clauses pour gérer le comportement lorsqu'une même clé primaire est trouvée. La clause IGNORE en fait partie. Lorsqu'elle est incluse dans une requête, elle indique à MySQL de transformer les erreurs signalant une clé dupliquée en avertissements. Il faut cependant faire attention en utilisant cette clause. Les erreurs lorsque l'on insère une valeur dans un champ NOT NULL ainsi que les erreurs de valeurs ne correspondant pas aux champs sont également ignorées pour une table partitionnée.

-- Soit la table ma_table avec deux champs, dont le champ champ1 comme clé primaire
INSERT INTO ma_table (champ1, champ2) VALUES (1,1);
...1 ligne(s) affectée(s)
INSERT INTO ma_table (uid,pid) VALUES (1,1);
...Error Code : 1062
...Duplicate entry '1' for key 'PRIMARY'
INSERT IGNORE INTO ma_table (champ1, champ2) VALUES (1,1);
...0 ligne(s) affectée(s)

Si l'on souhaite modifier la valeur des champs ayant la même clé primaire, on peut utiliser la commande REPLACE. Cette commande insère les enregistrements en base de données. Si un enregistrement avec la même clé primaire est trouvé, il est effacé. Il faut cependant faire attention lorsqu'on manipule cette commande car dans le cas d'enregistrements d'autres tables avec une clé étrangère ayant la contrainte ON DELETE CASCADE, ils seront supprimés. Les déclencheurs liés aux commandes DELETE seront lancés. Si vous ne précisez pas la nouvelle valeur de la clé primaire de l'enregistrement, alors un nouvel identifiant auto-incrémenté est utilisé.

REPLACE INTO ma_table (champ2) VALUES (2);
...2 ligne(s) affectée(s)
SELECT * FROM ma_table;
champ1 | champ2
2 | 2</pre>

SI l'on veut modifier les enregistrements qui sont détectés comment étant dupliqué, il faut utiliser la commande INSERT avec la clause ON DUPLICATE KEY. Vous pouvez ensuite préciser la manière dont la mise à jour est faite. Le mécanisme interne de la clause entraîne une modification de la valeur de l'incrémentation de la clé primaire. Bien que l'enregistrement ne change pas de clé primaire, la valeur de l'incrément est augmentée de 1 à chaque mise à jour.

<pre>INSERT INTO ma_table (champ1, champ2) VALUES (2,0) ON DUPLICATE KEY UPDATE champ2 = champ2 + 1
...1 ligne(s) affectée(s)
SELECT * FROM ma_table;
champ1 | champ2
2 | 3</pre>

Si vous ne souhaitez pas modifier la valeur, il existe une astuce, il suffit dans la requête UPDATE d'indiquer qu'une colonne est égale à elle-même. Cette clause n'entraîne aucune modification dans la base de données et la requête n'est pas exécutée.

<pre>INSERT INTO ma_table (champ1, champ2) VALUES (3,0) ON DUPLICATE KEY UPDATE champ2 = champ2
...0 ligne(s) affectée(s)</pre>

SQL