web-dev-qa-db-fra.com

Vérifiez toujours avec SELECT avant INSÉRER?

Si je veux INSERT une ligne uniquement si la clé primaire n'existe pas encore, est-il plus efficace/plus simple d'exécuter INSERT directement et d'ignorer l'erreur en cas de duplication, ou devrait je lance toujours SELECT pour vérifier s'il existe déjà en premier?

6
James

Vous pouvez utiliser WHERE NOT EXISTS pour vérifier les nouvelles valeurs avant d'insérer un nouvel enregistrement.

INSERT INTO <table>
(
    field1, field2, field3
)
SELECT value1, value2, value3
FROM dual
WHERE NOT EXISTS (SELECT 1
                  FROM <table>
                  WHERE <pk fields> = <new values>);
CREATE TABLE foo(id int, v1 int, v2 int);
INSERT INTO foo VALUES (1, 100,100);
INSERT INTO foo VALUES (2, 200, 200);

Cet enregistrement existe et ne doit pas être inséré:

INSERT INTO foo (id, v1, v2)
SELECT 1, 101, 101
FROM   dual
WHERE NOT EXISTS (SELECT 1 FROM foo WHERE id=1);

Voici un nouveau record:

INSERT INTO foo (id, v1, v2)
SELECT 3, 300, 300
FROM   dual
WHERE NOT EXISTS (SELECT 1 FROM foo WHERE id=3);

Le résultat final:

SELECT * FROM foo;
 id | v1 | v2 
 -: | -: | -: 
 1 | 100 | 100 
 2 | 200 | 200 
 3 | 300 | 300 

dbfiddle ici

4
McNets

La meilleure option (plus efficace) dépendra de la probabilité attendue de collision PK.

Si le risque de collision est élevé, je sauverais la surcharge DML et ferais le SELECT d'abord avant le potentiel INSERT.

Si le risque de collision est rare, il suffit probablement de faire un INSERT IGNORE.

Remarque: si le PK est un auto_increment, un échec INSERT IGNORE peut potentiellement gonfler le auto_increment (voir innodb_autoinc_lock_mode pour les options variables).

2
Riedsio

En général, IODKU est la meilleure façon:

INSERT INTO tbl ...
    ON DUPLICATE KEY UPDATE 
        ....

https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html

1
Rick James