Как составить запрос sql на вставку или обновление записи с проверкой по определенному полю?

accounts

id email social number
1 [email protected] vk 12235
2 [email protected] vk 53466
3 [email protected] fb 85643

Вставить запись если нет email или если есть с таким email и social то обновить number

email social number
[email protected] vk 25335
[email protected] fb 23568

Есть пример запроса, но не понял как его правильно описать

INSERT INTO table (id, email, social, number) VALUES (..., ...)
    ON DUPLICATE KEY UPDATE ... = ...;

Возможно подойдет какой то другой sql запрос


Ответы (3 шт):

Автор решения: Danil Apsadikov

Эту логику лучше всего перенести на сторону сервера, а не делать на стороне БД, так как это не явная логика работы приложения. Бд должна просто хранить и отдавать данные, все остальные манипуляции, связанные с бизнес процессами, должны быть на стороне сервера

→ Ссылка
Автор решения: c942o

Вы сами дали ответ. Так как Email уникальный, подразумевается, что он является ключом таблицы

INSERT INTO table (id, email, social, number) VALUES ('1','[email protected]','vk',1222)
ON DUPLICATE KEY UPDATE table set number = 2111;

либо есть вот такой вопрос на SO

→ Ссылка
Автор решения: Akina

Таблица должна иметь следующую структуру:

CREATE TABLE account (
    account_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    social VARCHAR(255) NOT NULL,
    number INT,
    UNIQUE (email, social)
);

Подробно:

  • Рекомендуется имя поля идентификатора-автоинкремента снабжать префиксом имени таблицы. Это позволяет иметь совершенно одноимённые поля при создании связей, а также избегать неоднозначностей в тексте запроса и не разбираться, какой таблице принадлежит безликое id. Серверу же всё равно, какая у имени поля длина - только не превышай установленный 64-байтовый предел.
  • Уникальный индекс по двум полям запретит вставку уже существующей в какой-то записи пары значений, но не будет реагировать, если значение где-то имеется значение только одного из двух полей. То же и при изменении - не получится изменить значения так, чтобы они совпали с парой значений в другой записи. Если это случится, сгенерируется ошибка дублирования. При вставке на это можно среагировать, и вместо вставки новой записи обновить существующую.

Соответственно запрос будет:

INSERT INTO account ( email, social, number )
VALUES ( {email}, {social}, {number} )
ON DUPLICATE KEY UPDATE number = VALUES(number);

Подробно:

  • Если вставляемой пары значений (email, social) в таблице ещё нет - запись будет вставлена с указанными значениями. Поле id не указано в списке, и, поскольку оно автоинкрементное, для него автоматически и скрыто будет сгенерировано новое значение. Часть запроса ON DUPLICATE KEY UPDATE в этом случае будет проигнорирована - ведь дублирования не было.
  • Если в таблице уже есть вставляемая пара значений (email, social), будет обнаружено дублирование. И ошибка дублирования будет обработана в ON DUPLICATE KEY UPDATE. В этой секции значение в поле number будет изменено на то значение, которое указано в секции VALUES (именно это делает использованная функция), а остальные поля не изменятся. Конечно, ничто не запрещает указать там иное значение или выражение - например, если написать number = number + VALUES(number), то указанное в VALUES значение будет прибавлено к существующему.
  • Если после применения изменений секции ON DUPLICATE KEY UPDATE будет обнаружена ошибка дублирования другого уникального индекса или этого, но с другой записью - это приведёт к ошибке исполнения запроса - ведь второго обработчика в запросе нет.
→ Ссылка