J'ai commencé par googler et j'ai trouvé cet article qui parle des tables mutex.
J'ai une table avec environ 14 millions d'enregistrements. Si je veux ajouter plus de données dans le même format, existe-t-il un moyen de s'assurer que l'enregistrement que je veux insérer n'existe pas déjà sans utiliser une paire de requêtes (c'est-à-dire, une requête à vérifier et une à insérer est l'ensemble de résultats est vide)?
Est-ce qu'une unique
contrainte sur un champ garantit l' insert
échec s'il est déjà là?
Il semble qu'avec une simple contrainte, lorsque j'émets l'insert via php, le script coasse.
mysql
sql
primary-key
sql-insert
garenne
la source
la source
Réponses:
utilisation
INSERT IGNORE INTO table
voir http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
il y a aussi la
INSERT … ON DUPLICATE KEY UPDATE
syntaxe, vous pouvez trouver des explications sur dev.mysql.comPublier sur bogdan.org.ua selon le webcache de Google :
la source
INSERT … ON DUPLICATE KEY UPDATE
est préférable car il ne supprime pas la ligne, préservant toutes lesauto_increment
colonnes et autres données.INSERT … ON DUPLICATE KEY UPDATE
méthode incrémente toute colonne AUTO_INCREMENT dont l'insertion a échoué. Probablement parce que ce n'est pas vraiment échoué, mais MIS À JOUR.Solution:
Explication:
La requête la plus profonde
utilisé comme
WHERE NOT EXISTS
-condition détecte s'il existe déjà une ligne avec les données à insérer. Une fois qu'une ligne de ce type a été trouvée, la requête peut s'arrêter, d'oùLIMIT 1
(la micro-optimisation peut être omise).La requête intermédiaire
représente les valeurs à insérer.
DUAL
fait référence à une table spéciale à une ligne et à une colonne présente par défaut dans toutes les bases de données Oracle (voir https://en.wikipedia.org/wiki/DUAL_table ). Sur une version 5.7.26 de MySQL-Server, j'ai reçu une requête valide lors de l'omissionFROM DUAL
, mais les versions plus anciennes (comme 5.5.60) semblent exiger lesFROM
informations. L'utilisation deWHERE NOT EXISTS
la requête intermédiaire renvoie un jeu de résultats vide si la requête la plus interne a trouvé des données correspondantes.La requête externe
insère les données, le cas échéant, est renvoyée par la requête intermédiaire.
la source
INSERT IGNORE
etINSERT ON DUPLICATE KEY
nécessite des contraintes de clé uniques)stuff for value1
etstuff for value2
sont identiques? Cela jetterait unDuplicate column name
SELECT 1
plutôt queSELECT *
dans les sous-requêtes. Il est beaucoup plus probable que cela puisse être satisfait par un indice.sur la mise à jour de clé en double , ou l' insertion d'ignorer peut être une solution viable avec MySQL.
Exemple de mise à jour de mise à jour de clé en double basée sur mysql.com
Exemple d' insertion ignorer basé sur mysql.com
Ou:
Ou:
la source
Toute contrainte simple devrait faire l'affaire, si une exception est acceptable. Exemples :
Désolé, cela semble d'une simplicité trompeuse. Je sais que ça fait mal face au lien que vous partagez avec nous. ;-(
Mais je donne toujours cette réponse, car elle semble répondre à votre besoin. (Sinon, cela peut déclencher la mise à jour de vos besoins, ce qui serait également "une bonne chose" (TM)).
Modifié : si une insertion rompait la contrainte unique de la base de données, une exception est levée au niveau de la base de données, relayée par le pilote. Cela arrêtera certainement votre script, avec un échec. Il doit être possible en PHP de traiter ce cas ...
la source
INSERT IGNORE
transforme essentiellement toutes les erreurs en avertissements afin que votre script ne soit pas interrompu. Vous pouvez ensuite afficher tous les avertissements avec la commandeSHOW WARNINGS
. Et une autre remarque importante : les contraintes UNIQUES ne fonctionnent pas avec les valeurs NULL, c'est-à-dire. row1 (1, NULL) et row2 (1, NULL) seront tous deux insérés (sauf si une autre contrainte telle qu'une clé primaire est cassée). Malheureux.Voici une fonction PHP qui insérera une ligne uniquement si toutes les valeurs de colonnes spécifiées n'existent pas déjà dans la table.
Si l'une des colonnes diffère, la ligne sera ajoutée.
Si le tableau est vide, la ligne sera ajoutée.
S'il existe une ligne où toutes les colonnes spécifiées ont les valeurs spécifiées, la ligne ne sera pas ajoutée.
Exemple d'utilisation:
la source
mysql_*
extension est obsolète à partir de PHP 5.5.0 et a été supprimée à partir de PHP 7.0.0. À la place, l' extension mysqli ou PDO_MySQL doit être utilisée. Voir également la Présentation de l'API MySQL pour plus d'aide lors du choix d'une API MySQL.Si l'enregistrement existe, il sera écrasé; s'il n'existe pas encore, il sera créé.
la source
REPLACE
peut supprimer la ligne, puis insérer au lieu de la mise à jour. L'effet secondaire est que les contraintes peuvent supprimer d'autres objets et que les déclencheurs de suppression sont déclenchés.Essayez ce qui suit:
la source
Il existe plusieurs réponses qui expliquent comment résoudre ce problème si vous disposez d'un
UNIQUE
index que vous pouvez vérifier avecON DUPLICATE KEY
ouINSERT IGNORE
. Ce n'est pas toujours le cas, et commeUNIQUE
pour une contrainte de longueur (1000 octets), vous ne pourrez peut-être pas changer cela. Par exemple, j'ai dû travailler avec des métadonnées dans WordPress (wp_postmeta
).Je l'ai finalement résolu avec deux requêtes:
La requête 1 est une
UPDATE
requête régulière sans effet lorsque l'ensemble de données en question n'est pas là. La requête 2 est unINSERT
qui dépend de aNOT EXISTS
, c'est-à-INSERT
dire que n'est exécuté que lorsque l'ensemble de données n'existe pas.la source
Il convient de noter que INSERT IGNORE incrémentera toujours la clé primaire, que l'instruction soit un succès ou non, tout comme le ferait un INSERT normal.
Cela entraînera des lacunes dans vos clés primaires qui pourraient rendre un programmeur mentalement instable. Ou si votre application est mal conçue et dépend de clés primaires incrémentielles parfaites, cela pourrait devenir un casse-tête.
Examinez
innodb_autoinc_lock_mode = 0
(paramètre du serveur et est accompagné d'un léger hit de performance), ou utilisez d'abord SELECT pour vous assurer que votre requête n'échouera pas (qui est également fournie avec un hit de performance et du code supplémentaire).la source
SELECT
échoue dans le seul but de distribuer un gros lot deINSERT
s et de ne pas vouloir se soucier des doublons.Mettre à jour ou insérer sans clé primaire connue
Si vous avez déjà une clé unique ou primaire, les autres réponses avec soit
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
ouREPLACE INTO ...
devraient fonctionner correctement (notez que remplacer en supprime s'il existe puis insère - donc ne met pas à jour partiellement les valeurs existantes).Mais si vous avez les valeurs pour
some_column_id
etsome_type
dont la combinaison est connue pour être unique. Et vous souhaitez mettre à joursome_value
s'il existe, ou insérer s'il n'existe pas. Et vous voulez le faire en une seule requête (pour éviter d'utiliser une transaction). Cela pourrait être une solution:Fondamentalement, la requête s'exécute de cette façon (moins compliquée qu'elle n'y paraît):
WHERE
correspondance de clause.s
), où les valeurs de colonne sont explicitement données (s.id est NULL, donc il va générer un nouvel identifiant d'incrémentation automatique).s
est ignorée (en raison de LIMIT 1 sur la tablet
), et elle déclenchera toujours uneON DUPLICATE KEY
qui seraUPDATE
lasome_value
colonne.s
).Remarque: Chaque table dans une base de données relationnelle doit avoir au moins une incrémentation automatique principale
id
colonne d' . Si vous ne l'avez pas, ajoutez-le, même lorsque vous n'en avez pas besoin à première vue. Il est absolument nécessaire pour ce "truc".la source
INSERT INTO ... SELECT FROM
format. Pourquoi aussi?INSERT INTO... SELECT FROM...
solution régulière . Veuillez me renvoyer un lien vers une réponse identique, si vous pouvez la trouver, je supprimerai cette réponse, sinon vous votez positivement ma réponse (deal?). Assurez-vous de vérifier que la réponse que vous allez lier n'utilise qu'une seule requête (pour la mise à jour + l'insertion), aucune transaction et est capable de cibler n'importe quelle combinaison de colonnes connues pour être uniques (donc séparément les colonnes ne le font pas doivent être uniques).