MySql Table Insert, если не существует, иначе обновить


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

Он работает, если он datenumсуществует, но я хочу вставить эти данные как новую строку, если datenumон не существует.

ОБНОВИТЬ

datenum уникален, но это не первичный ключ


2
"Datenum" уникален? Вы можете использовать INSERT ... ON DUPLICATE KEY UPDATE, если это так.
Джейкоб

Ответы:


143

Джай прав, что вы должны использовать INSERT ... ON DUPLICATE KEY UPDATE.

Обратите внимание, что вам не нужно включать datenum в предложение обновления, поскольку это уникальный ключ, поэтому он не должен меняться. Вам необходимо включить все остальные столбцы из вашей таблицы. Вы можете использовать эту VALUES()функцию, чтобы убедиться, что при обновлении других столбцов используются правильные значения.

Вот ваше обновление, переписанное с использованием правильного INSERT ... ON DUPLICATE KEY UPDATEсинтаксиса MySQL:

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

18
Будьте осторожны при использовании INSERT ... ON DUPLICATE KEY UPDATE в таблицах против таблицы, имеющей более одного уникального или первичного ключа. Взято из документации MySQL : Кроме того, начиная с MySQL 5.5.24, оператор INSERT ... ON DUPLICATE KEY UPDATE для таблицы, имеющей более одного уникального или первичного ключа, также помечается как небезопасный. (Ошибка № 11765650, Ошибка № 58637) Описание ошибки 58637 bugs.mysql.com/bug.php?id=58637
широкополосная связь

1
Может потребоваться создать UNIQUEограничение Timestampс помощьюALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt

@broadband, вы можете использовать составной ключ, чтобы избежать этой ошибки
Карим,

16

Попробуйте использовать это :

Если вы укажете ON DUPLICATE KEY UPDATE, и будет вставлена ​​строка, которая вызовет дублирование значения в UNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) старой строки. ..

Предложение ON DUPLICATE KEY UPDATEможет содержать несколько назначений столбцов, разделенных запятыми.

С ON DUPLICATE KEY UPDATE, значение затронутых строк для каждой строки равно 1, если строка вставляется как новая строка, 2, если существующая строка обновляется, и 0, если для существующей строки заданы ее текущие значения. Если вы укажете CLIENT_FOUND_ROWSфлаг mysql_real_connect()при подключении к mysqld , значение затронутых строк будет 1 (не 0), если для существующей строки заданы текущие значения ...


Но мой datenum не первичный ключ.
OHLÁLÁ

Итак, в моем случае, каково решение, я попробовал это, без какого-либо решения: INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ

1
должно ли datenum быть уникальным? если да, то добавьте к нему уникальный индекс (если он еще не добавлен), тогда он будет работать. Обратитесь к dev.mysql.com/doc/refman/5.1/en/alter-table.html, чтобы узнать, как размещать УНИКАЛЬНЫЕ индексы
Джай

теперь я определил datenum как уникальный, и он работает нормально, спасибо
OHLÁLÁ

1
Просто ссылку, может ответ дадите.
Эндрю

0

У меня была ситуация, когда мне нужно было обновить или вставить в таблицу в соответствии с двумя полями (оба внешних ключа), для которых я не мог установить ограничение UNIQUE (поэтому INSERT ... ON DUPLICATE KEY UPDATE не сработает). Вот что я в итоге использовал:

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;

Этот пример взят из одной из моих баз данных, при этом входные параметры (два имени и номер) заменены на [hasher_name], [hash_name] и [new_value]. Вложенный SELECT ... LIMIT 1 извлекает первую из существующей записи или новой записи (last_recogs.id - это первичный ключ с автоинкрементом) и использует это как значение, вводимое в REPLACE INTO.


REPLACE всегда вставляет новую строку! он просто удаляет исходный, уже существующий!
jasie
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.