Как составить запрос sql на вставку или обновление записи с проверкой по определенному полю?
accounts
| id | social | number | |
|---|---|---|---|
| 1 | [email protected] | vk | 12235 |
| 2 | [email protected] | vk | 53466 |
| 3 | [email protected] | fb | 85643 |
Вставить запись если нет email или если есть с таким email и social то обновить number
| social | number | |
|---|---|---|
| [email protected] | vk | 25335 |
| [email protected] | fb | 23568 |
Есть пример запроса, но не понял как его правильно описать
INSERT INTO table (id, email, social, number) VALUES (..., ...)
ON DUPLICATE KEY UPDATE ... = ...;
Возможно подойдет какой то другой sql запрос
Ответы (3 шт):
Эту логику лучше всего перенести на сторону сервера, а не делать на стороне БД, так как это не явная логика работы приложения. Бд должна просто хранить и отдавать данные, все остальные манипуляции, связанные с бизнес процессами, должны быть на стороне сервера
Вы сами дали ответ. Так как Email уникальный, подразумевается, что он является ключом таблицы
INSERT INTO table (id, email, social, number) VALUES ('1','[email protected]','vk',1222)
ON DUPLICATE KEY UPDATE table set number = 2111;
либо есть вот такой вопрос на SO
Таблица должна иметь следующую структуру:
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будет обнаружена ошибка дублирования другого уникального индекса или этого, но с другой записью - это приведёт к ошибке исполнения запроса - ведь второго обработчика в запросе нет.