#mysql #sql #json #duplicates #sql-insert
#mysql #sql #json #дубликаты #sql-вставка
Вопрос:
Предположим, у меня есть таблица user
:
PK id: int
firstname: varchar
lastname: varchar
FK group_id: int
И таблица group
:
PK id: int
name: varchar
Теперь я хочу иметь возможность отправлять на сервер объект student JSON, который содержит:
{
"firstname": "john",
"lastname": "doe",
"group": "group_name"
}
Как вставить его в таблицы? Как я могу убедиться, что строка с «имя_группы» существует, и если нет, создайте ее, а затем и только тогда вставьте ученика с соответствующим FK group_id?
Что бы я сделал, это что-то вроде:
- выберите идентификатор из группы, где name=»имя_группы»
- если не существует: вставить в значения группы («имя_группы»)
- вставить в пользовательские значения («john», «doe», the_existing_or_newly_inserted_group_id)
Но это кажется немного излишним с точки зрения количества запросов.
Ответ №1:
В MySQL вы можете сделать это всего двумя операторами:
insert into groups (group_name)
select s.group_name
from (select :group_name as group_name) s
where not exists (select 1 from groups g where g.group_name = s.group_name);
insert into users (firstname, lastname, group_id)
select :firstname, :lastname, g.group_id
from groups g
where g.group_name = :group_name;
Первый оператор создает новую группу, если она еще не существует. Второй оператор восстанавливает идентификатор группы и вставляет информацию о пользователе.
Для правильной работы group_name
в таблице должен быть уникальный ключ groups
.
Примечания:
-
Возможно, вы захотите обернуть инструкции в одну транзакцию, чтобы параллелизм правильно управлялся
-
Значения, которым предшествует,
:
представляют параметры запросов, которые должны быть переданы из приложения -
Оба
user
иgroup
являются ключевыми словами языка, следовательно, плохой выбор имен объектов; Я изменил имена таблиц наusers
иgroups
.
Комментарии:
1. If
group_name
определяется как уникальный (но он должен!), Тогдаinsert ignore into groups
он более прост и полезен (и не нуждается в WHERE).2. @Akina: да, или
on duplicate key
… Но я пытался не записывать порядковые номера, такnot exists
что .