<rmcreative>

RSS

MySQL: добавить если ещё нет

19 декабря 2008

Иногда требуется вставить запись в таблицу, если её там до сих пор нет. Можно сделать пару запросов: одним —проверить, другим — вставить, а можно и одним:

INSERT IGNORE INTO `users`
SET `login` = 'samdark', `password` = 'mypassword';

Поле login должно быть уникальным.

Комментарии RSS

  1. №982
    Andrey
    Andrey 19 дек. 2008 г., 15:17:51

    Похожая задача - если нужно вставить, а если уже есть - изменить.

    INSERT INTO users(login, password) VALUES('login', 'password') ON DUPLICATE KEY UPDATE password='password';

  2. №983
    Shadow
    Shadow 19 дек. 2008 г., 16:24:24

    Andrey, а почему не replace?

    REPLACE INTO users (`login`, `password`) VALUES('login', 'password');
  3. №984
    Andrey
    Andrey 19 дек. 2008 г., 16:28:22

    Shadow, честно говоря ни разу не пользовался, но подозреваю, что здесь есть разница. Например, если у нас есть таблица-счетчик, и нам нужно в случае первого посещения вставить запись, а в случае следующих - увеличить счетчик на единицу. Тогда пользуемся ON DUPLICATE KEY UPDATE counter=counter+1

  4. №985
    Sam
    Sam 19 дек. 2008 г., 16:29:16

    Shadow

    REPLACE будет перетирать существующие данные, не пропускать, как в случае с INSERT IGNORE.

  5. №986
    Sam
    Sam 19 дек. 2008 г., 16:37:17

    Оу… сорри, не заметил начала сообщения :)

  6. №987
    Андрей
    Андрей 19 дек. 2008 г., 16:38:25

    Sam, ну мы как бы не об аналоге говорим, а о похожих случаях. Никто не спорит, что оно не работает аналогично.

  7. №988
    Алексей Качаев
    Алексей Качаев 19 дек. 2008 г., 19:09:03

    ...Можно сделать пару запросов: одним —проверить, другим — вставить...

    Ни в коем случае так делать нельзя! Это грубая ошибка. Между первым запросом и вторым пройдет какое-то время. Вполне может оказать, что именно в этот промежуток другой процесс создаст записей, в отсутствии которой вы только что убедились.

  8. №989
    Dr.Death
    Dr.Death 19 дек. 2008 г., 19:16:20

    век живи век учись :)

  9. №990
    Андрей
    Андрей 19 дек. 2008 г., 20:21:11

    Алексей, в mysql, если я не ошибаюсь, есть транзакции. А до транзакций для этой цели существовала блокировка таблиц, которая работает и сейчас. То есть в самой проверке-вставке никакой грубой ошибки нет. Другое дело, что это повышает вероятность ошибки из-за того, что программист забудет вставить блокировку, или забудет вовремя разблокировать таблицу.

  10. №991
    Олег
    Олег 20 дек. 2008 г., 13:28:24

    Проверка и обновление в два запроса в одной транзакции зато гораздо более переносимое решение.

  11. №1499
    mihdan
    mihdan 14 апр. 2009 г., 11:12:21

    Век живи-век учись. Спасибо. Пригодилось

  12. №6503
    Rash
    Rash 30 июля 2012 г., 14:20:15

    Отлично, спасибо за пример, очень пригодилось.

  13. №8127
    Сергей
    Сергей 04 июля 2013 г., 11:53:42

    Уже не первый день с SQL, и вроде бы такой простой вопрос, а вот только что нашел решение. Большое спасибо!

  14. №9847
    Роман
    Роман 14 июня 2015 г., 19:50:05

    А как быть, если во первых: поля не уникальны; во вторых - нужно смотреть по двум колонкам, если совпадают обе - не пишем, если одна - пишем ?

  15. №10619
    Владимир
    Владимир 12 авг. 2016 г., 14:16:06

    Спасибо, у меня получилось, пока не поставил нужное поле PRIMARY KEY или UNIQUE.

  16. №11003
    Стас
    Стас 24 мая 2017 г., 18:18:12

    Здравствуйте а как быть если до вставки ещё выполняется много функций, как перед их выполнением проверить на дубликат с помощью INSERT IGNORE INTO? Вот кучу дублей на собиралось

  17. №11153
    Евгений
    Евгений 31 дек. 2017 г., 0:23:48

    Похожая функция для тех, кто использует 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

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.