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

It works if the datenum exists, but I want to insert this data as a new row if the datenum does not exist.

UPDATE

the datenum is unique but that's not the primary key

Mokus
  • 10,174
  • 18
  • 80
  • 122
  • 2
    Is "datenum" unique? You could use [INSERT ... ON DUPLICATE KEY UPDATE](http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html) if it is. – Jacob May 17 '11 at 11:29
  • 3
    Possible duplicate of [Insert into a MySQL table or update if exists](http://stackoverflow.com/questions/4205181/insert-into-a-mysql-table-or-update-if-exists) – Jim Fell Jun 07 '16 at 14:40

4 Answers4

154

Jai is correct that you should use INSERT ... ON DUPLICATE KEY UPDATE.

Note that you do not need to include datenum in the update clause since it's the unique key, so it should not change. You do need to include all of the other columns from your table. You can use the VALUES() function to make sure the proper values are used when updating the other columns.

Here is your update re-written using the proper INSERT ... ON DUPLICATE KEY UPDATE syntax for MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)
Ike Walker
  • 64,401
  • 14
  • 110
  • 109
  • 18
    Be careful when using INSERT ... ON DUPLICATE KEY UPDATE on tables against a table having more than one unique or primary key. Taken from [MySQL documentation](http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html): _In addition, beginning with MySQL 5.5.24, an INSERT ... ON DUPLICATE KEY UPDATE statement against a table having more than one unique or primary key is also marked as unsafe. (Bug #11765650, Bug #58637)_ Bug 58637 description http://bugs.mysql.com/bug.php?id=58637 – broadband Sep 02 '14 at 13:28
  • 1
    It might be needed to create `UNIQUE` constraint for `Timestamp` by using `ALTER TABLE AggregatedData ADD UNIQUE (Timestamp)` – Avyakt Jan 19 '15 at 19:13
  • @broadband you can use a [composite key](https://stackoverflow.com/questions/5835978/how-to-properly-create-composite-primary-keys-mysql) to avoid this bug – Kareem Apr 24 '19 at 09:46
  • the best answer – Plugie May 13 '23 at 03:55
18

Try using this:

If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index orPRIMARY KEY, MySQL performs an [UPDATE`](http://dev.mysql.com/doc/refman/5.7/en/update.html) of the old row...

The ON DUPLICATE KEY UPDATE clause can contain multiple column assignments, separated by commas.

With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is 1 (not 0) if an existing row is set to its current values...

gnat
  • 6,213
  • 108
  • 53
  • 73
Jai
  • 3,549
  • 3
  • 23
  • 31
  • But my datenum not the primary key. – Mokus May 17 '11 at 11:49
  • So in my case what is the solution, I tried this one, without any solution:INSERT INTO forwind.aggregateddata (datenum,Timestamp,Min_F1_baro_20_) VALUES ('1','2','3') ON DUPLICATE KEY UPDATE datenum=datenum; – Mokus May 17 '11 at 11:57
  • 1
    is datenum supposed to be unique? if yes, than add a unique index to it (if not already added) Then it will work. Refer http://dev.mysql.com/doc/refman/5.1/en/alter-table.html for how to ad UNIQUE indexes – Jai May 17 '11 at 14:01
  • now I defined the datenum as unique, and it's work fine, thanks – Mokus May 18 '11 at 08:21
  • 1
    Just a link, maybe give an answer. – Andrew Jan 15 '16 at 21:48
1

This is not too bad, but we could actually combine everything into one query. I found different solutions on the internet. The simplest, but MySQL only solution is this:

INSERT INTO wp_postmeta (post_id, meta_key) 
SELECT 
  ?id, 
  ‘page_title’ 
FROM 
  DUAL 
WHERE 
  NOT EXISTS (
    SELECT 
      meta_id 
    FROM 
      wp_postmeta 
    WHERE 
      post_id = ?id 
      AND meta_key = ‘page_title’
  );
UPDATE 
  wp_postmeta 
SET 
  meta_value = ?page_title 
WHERE 
  post_id = ?id 
  AND meta_key = ‘page_title’;

Link to documentation.

James Risner
  • 5,451
  • 11
  • 25
  • 47
0

I had a situation where I needed to update or insert on a table according to two fields (both foreign keys) on which I couldn't set a UNIQUE constraint (so INSERT ... ON DUPLICATE KEY UPDATE won't work). Here's what I ended up using:

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;

This example is cribbed from one of my databases, with the input parameters (two names and a number) replaced with [hasher_name], [hash_name], and [new_value]. The nested SELECT...LIMIT 1 pulls the first of either the existing record or a new record (last_recogs.id is an autoincrement primary key) and uses that as the value input into the REPLACE INTO.

salfter
  • 119
  • 1
  • 3