Insérer une table MySql s'il n'existe pas sinon mettre à jour


105
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

Cela fonctionne si le datenumexiste, mais je veux insérer ces données en tant que nouvelle ligne si le datenumn'existe pas.

METTRE À JOUR

le datenum est unique mais ce n'est pas la clé primaire


2
Le "datenum" est-il unique? Vous pouvez utiliser INSERT ... ON DUPLICATE KEY UPDATE si c'est le cas.
Jacob

Réponses:


143

Jai a raison de l'utiliser INSERT ... ON DUPLICATE KEY UPDATE.

Notez que vous n'avez pas besoin d'inclure le datenum dans la clause de mise à jour car il s'agit de la clé unique, elle ne doit donc pas changer. Vous devez inclure toutes les autres colonnes de votre table. Vous pouvez utiliser la VALUES()fonction pour vous assurer que les valeurs appropriées sont utilisées lors de la mise à jour des autres colonnes.

Voici votre mise à jour réécrite en utilisant la INSERT ... ON DUPLICATE KEY UPDATEsyntaxe appropriée pour MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)

18
Soyez prudent lorsque vous utilisez INSERT ... ON DUPLICATE KEY UPDATE sur des tables par rapport à une table ayant plus d'une clé unique ou primaire. Tiré de la documentation MySQL : De plus, à partir de MySQL 5.5.24, une instruction INSERT ... ON DUPLICATE KEY UPDATE contre une table ayant plus d'une clé unique ou primaire est également marquée comme non sécurisée. (Bogue # 11765650, Bogue # 58637) Description du bogue 58637 bugs.mysql.com/bug.php?id=58637
haut débit le

1
Il peut être nécessaire de créer une UNIQUEcontrainte pour Timestampen utilisantALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt

@broadband, vous pouvez utiliser une clé composite pour éviter ce bug
Kareem

16

Essayez d'utiliser ceci :

Si vous spécifiez ON DUPLICATE KEY UPDATE, et une ligne est insérée qui provoquerait une valeur en double dans une UNIQUE index orclé primaire , MySQL performs an [update`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) de l'ancienne ligne. ..

La ON DUPLICATE KEY UPDATEclause peut contenir plusieurs affectations de colonnes, séparées par des virgules.

Avec ON DUPLICATE KEY UPDATE, la valeur des lignes affectées par ligne est 1 si la ligne est insérée en tant que nouvelle ligne, 2 si une ligne existante est mise à jour et 0 si une ligne existante est définie sur ses valeurs actuelles. Si vous spécifiez l' CLIENT_FOUND_ROWSindicateur mysql_real_connect()lors de la connexion à mysqld , la valeur des lignes affectées est 1 (et non 0) si une ligne existante est définie sur ses valeurs actuelles ...


Mais ma donnée n'est pas la clé primaire.
OHLÁLÁ

Donc dans mon cas quelle est la solution, j'ai essayé celle-ci, sans aucune solution: INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ

1
Le datenum est-il censé être unique? si oui, ajoutez-y un index unique (s'il n'est pas déjà ajouté). Ensuite, cela fonctionnera. Référez-vous à dev.mysql.com/doc/refman/5.1/en/alter-table.html pour savoir comment publier des index UNIQUE
Jai

maintenant j'ai défini le datenum comme unique, et ça marche bien, merci
OHLÁLÁ

1
Juste un lien, peut-être donner une réponse.
Andrew

0

J'ai eu une situation où j'avais besoin de mettre à jour ou d'insérer sur une table selon deux champs (les deux clés étrangères) sur lesquelles je ne pouvais pas définir une contrainte UNIQUE (donc INSERT ... ON DUPLICATE KEY UPDATE ne fonctionnera pas). Voici ce que j'ai fini par utiliser:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

Cet exemple est tiré d'une de mes bases de données, avec les paramètres d'entrée (deux noms et un nombre) remplacés par [hasher_name], [hash_name] et [new_value]. Le SELECT ... LIMIT 1 imbriqué extrait le premier de l'enregistrement existant ou d'un nouvel enregistrement (last_recogs.id est une clé primaire à auto-incrémentation) et l'utilise comme valeur d'entrée dans REPLACE INTO.


REPLACE insère toujours une nouvelle ligne! il supprime simplement l'original, déjà existant!
jasie
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.