MySQL: добавить если ещё нет
19 декабря 2008
Иногда требуется вставить запись в таблицу, если её там до сих пор нет. Можно сделать пару запросов: одним —проверить, другим — вставить, а можно и одним:
INSERT IGNORE INTO `users` SET `login` = 'samdark', `password` = 'mypassword';
Поле login
должно быть уникальным.
Комментарии RSS по email OK
Похожая задача - если нужно вставить, а если уже есть - изменить.
INSERT INTO users(
login
,password
) VALUES('login', 'password') ON DUPLICATE KEY UPDATEpassword
='password';Andrey, а почему не replace?
Shadow, честно говоря ни разу не пользовался, но подозреваю, что здесь есть разница. Например, если у нас есть таблица-счетчик, и нам нужно в случае первого посещения вставить запись, а в случае следующих - увеличить счетчик на единицу. Тогда пользуемся ON DUPLICATE KEY UPDATE counter=counter+1
Shadow
REPLACE будет перетирать существующие данные, не пропускать, как в случае с INSERT IGNORE.
Оу… сорри, не заметил начала сообщения :)
Sam, ну мы как бы не об аналоге говорим, а о похожих случаях. Никто не спорит, что оно не работает аналогично.
...Можно сделать пару запросов: одним —проверить, другим — вставить...
Ни в коем случае так делать нельзя! Это грубая ошибка. Между первым запросом и вторым пройдет какое-то время. Вполне может оказать, что именно в этот промежуток другой процесс создаст записей, в отсутствии которой вы только что убедились.
век живи век учись :)
Алексей, в mysql, если я не ошибаюсь, есть транзакции. А до транзакций для этой цели существовала блокировка таблиц, которая работает и сейчас. То есть в самой проверке-вставке никакой грубой ошибки нет. Другое дело, что это повышает вероятность ошибки из-за того, что программист забудет вставить блокировку, или забудет вовремя разблокировать таблицу.
Проверка и обновление в два запроса в одной транзакции зато гораздо более переносимое решение.
Век живи-век учись. Спасибо. Пригодилось
Отлично, спасибо за пример, очень пригодилось.
Уже не первый день с SQL, и вроде бы такой простой вопрос, а вот только что нашел решение. Большое спасибо!
А как быть, если во первых: поля не уникальны; во вторых - нужно смотреть по двум колонкам, если совпадают обе - не пишем, если одна - пишем ?
Спасибо, у меня получилось, пока не поставил нужное поле PRIMARY KEY или UNIQUE.
Здравствуйте а как быть если до вставки ещё выполняется много функций, как перед их выполнением проверить на дубликат с помощью INSERT IGNORE INTO? Вот кучу дублей на собиралось
Похожая функция для тех, кто использует Postgresql 9.5+. При обычной вставке добавить ON CONFLICT, поле, действие при обнаружении дубликата (пропустить или перезаписать). Пример: INSERT INTO distributors (id, dname) VALUES (7, 'Redline GmbH') ON CONFLICT (id) DO NOTHING; Ссылка на документацию: www.postgresql.org/docs/9.5/static/sql-insert.html