У меня есть таблица MySQL, в которой записаны классифицированные списки. Мы не вынуждаем пользователей присоединяться к публикации, и поэтому с этим списком не всегда ассоциируется user_id.
Поэтому мне нужен способ записи электронной почты автора, если он не вошел в систему.
Каков бизнес-ключ вашей пользовательской сущности? Или, более прямо: что является вашей пользовательской сущностью? Является ли каждый отдельный адрес электронной почты ключом для сущности «Пользователь», когда некоторые пользователи зарегистрировались, а их адрес электронной почты задан в каком-то профиле, а другие не зарегистрированы и дают адрес электронной почты каждый раз, когда они публикуют? Или у вас есть две разные сущности, RegisteredUser и UnknownPosterWithEmailAddress, их атрибуты хранятся в разных местах?
В последнем случае вы бы использовали NULLable user_id и NULLable поле электронной почты, как вы предложили, но затем запросы типа «для данного сообщения, найти адрес электронной почты, на который должен быть отправлен ответ», будут неудобны например, список всех постов с соответствующими адресами ответов будет выглядеть так:
select post.id,
case when post.user_id is not null then user.email
else post.email end as email
from post
left join user on user.id=post.user_id;
Через некоторое время это может стать очень грязным.
Я бы предпочел использовать первый подход: каждая строка в User представляет собой постер dsitinct с уникальным адресом электронной почты, не равным NULL, и суррогатным ключом в качестве внешнего ключа в сообщениях:
create table user(id integer primary key,
email text not null unique,
is_registered boolean default false);
create table post(id integer primary key,
user_id integer not null references user(id),
content text);
Если незарегистрированный пользователь вводит адрес электронной почты, вы просматриваете его в таблице пользователей и извлекаете user.id, добавляя новую запись в пользователя, если это необходимо. В результате вы можете ответить на такие вопросы, как: для данного адреса электронной почты, сколько сообщений сделал этот пользователь за последнюю неделю? через поле внешнего ключа, без необходимости сравнивать строки в некотором поле атрибута NULLable.
Когда пользователь выбирает регистрацию, вы можете добавить регистрационные данные либо в самом пользователе, либо в какую-то отдельную таблицу (опять же с user.id в качестве внешнего ключа, некоторые могут утверждать, что логическое поле is_registered тогда фактически избыточно). Дополнительные преимущества:
- Если он публиковал сообщения ранее под тем же адресом электронной почты, теперь все его старые сообщения автоматически связываются с его новой зарегистрированной личностью.
- Если пользователь изменяет свой адрес электронной почты в своем профиле, все ответы на старые сообщения его "видят" новый обновленный адрес электронной почты.