Как смоделировать это отношение один к одному? - PullRequest
0 голосов
/ 14 апреля 2010

У меня есть несколько сущностей, которые представляют разных типов пользователей, которым необходимо иметь возможность войти в определенную систему. Кроме того, с ними связана различная информация.

Например: «обычный пользователь» с адресом электронной почты и «пользователь-администратор» с номером рабочей станции (обратите внимание, что это гипотетический случай). Обе организации также имеют общие свойства, такие как имя, фамилия, адрес и номер телефона. Наконец, им, естественно, нужно иметь (уникальное) имя пользователя и пароль для входа в систему.

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

Как мне эффективно смоделировать это?

Я не могу просто создать две таблицы, потому что тогда я не могу навязать уникальное содержимое имени пользователя.

Я также не могу поместить их всех в одну таблицу, потому что с ними связаны разные типы специфической информации.

Я думаю, что мне могут понадобиться 3 отдельные таблицы, одна для «пользователей» (с именем пользователя и паролем), одна для «обычных пользователей» и другая для «пользователей-администраторов», но как будут работать эти отношения ? Или есть другое решение?

(Кстати, целевой СУБД является MySQL, поэтому я не думаю, что обобщение поддерживается в самой системе баз данных).

Ответы [ 5 ]

0 голосов
/ 14 апреля 2010

Я определенно не буду делать модель, в которой у вас есть отдельные таблицы, как в GeneralUser, AdminUser и ReadOnlyUser.

При проектировании базы данных хорошее правило: "Удар вниз" . Вместо нескольких таблиц (по одной для каждого типа) я бы создал таблицу SystemUsers и таблицу Roles и определил таблицу соединений, чтобы поместить SystemUsers в роли. Также я бы определил отдельные роли.

Таким образом, пользователь может быть добавлен и удален из нескольких ролей.

Роль может иметь несколько разрешений, которые могут быть изменены в любое время.

Соединения с другими местами не нуждаются в столбцах GeneralUserId, AdminUserId и ReadOnlyUserId - только столбец SystemUserId.

Это очень похоже на модель безопасности на основе ролей ASP.Net.

альтернативный текст http://img52.imageshack.us/img52/2861/rolebasedsecurity.jpg

0 голосов
/ 14 апреля 2010

Вы можете решить эту проблему с помощью одной «общей» таблицы пользователей, содержащей информацию, доступную для всех пользователей, и 1 таблицы для каждого конкретного типа пользователя. В вашем примере вам понадобятся 3 таблицы.

Пользователи: в этой таблице хранится только информация, общая для всех типов пользователей, т.е. ИД пользователя, имя, адрес и т. Д.

GeneralUsers: эта таблица «расширяет» таблицу Users, предоставляя первичный ключ UserId, который ссылается на таблицу Users. Кроме того, информация, характерная для обычных пользователей, хранится здесь, fx. Адрес электронной почты и т. Д.

AdminUsers: как и в случае с GeneralUsers, эта таблица также «расширяет» таблицу Users, предоставляя внешний ключ UserId, ссылающийся на таблицу Users. Кроме того, информация, специфичная для пользователей-администраторов, хранится здесь, fx. WorkstationId и т. Д.

При таком подходе вы можете добавлять дополнительные «специализации», если возникает необходимость, просто добавляя новые таблицы, которые «расширяют» таблицу Users, используя ссылку на внешний ключ. Вы также можете создать несколько уровней специализации. Если, например, пользователи-администраторы являются обычными пользователями, а также пользователями-администраторами, то AdminUsers могут «расширять» GeneralUsers вместо Users, просто используя ключ доступа к GeneralUsers вместо Users.

Когда вам нужно получить данные из этой модели, вам нужно, к какому типу пользователей обращаться. Если, например, вам нужно запросить GeneralUser, вам нужно что-то похожее на:

SELECT * FROM GeneralUsers СЛЕДУЮЩИЙ ПРИСОЕДИНЯЙТЕСЬ К ПОЛЬЗОВАТЕЛЯМ НА GeneralUsers.UserId = Users.UserId

Или при запросе пользователя с правами администратора

SELECT * FROM AdminUsers СЛЕДУЮЩИЙ ПРИСОЕДИНЯЙТЕСЬ К ПОЛЬЗОВАТЕЛЯМ НА AdminUsers.UserId = Users.UserId

Если у вас есть дополнительные уровни специализации, например, если пользователи-администраторы также являются обычными пользователями, вы просто возвращаетесь.

SELECT * FROM AdminUsers СЛЕДУЮЩИЙ ПРИСОЕДИНЯЙТЕСЬ к GeneralUsers ON AdminUsers.UserId = GeneralUsers.UserId СЛЕДУЮЩИЙ ПРИСОЕДИНЯЙТЕСЬ К ПОЛЬЗОВАТЕЛЯМ НА GeneralUsers.UsersId = Users.UserId

0 голосов
/ 14 апреля 2010

Ваш подход к 3 столам выглядит нормально. В таблице пользователей есть только идентификатор, имя пользователя, пароль, тип пользователя. В общем случае таблица пользователей имеет идентификатор, идентификатор пользователя (из таблицы пользователей), другие поля. То же самое для пользователей с правами администратора.

Поле Usertype сообщит вам, из какой таблицы искать дополнительную информацию

if(usertype==admin)
  select * from  admins where userid=:id;
else    
  select * from  general where userid=:id;
0 голосов
/ 14 апреля 2010

Вы должны решить, сколько конкретной информации хранится (или, вероятно, будет сохранено в будущем), и принять решение на основе этого. Если есть только несколько полей для каждого пользовательского типа, тогда можно использовать одну таблицу.

Таблица ПОЛЬЗОВАТЕЛЕЙ (имя, тип, адрес электронной почты, пароль, genfield1, genfield2, adminfield1, adminfield2)

Убедитесь, что вы включили поле типа (не предполагайте, потому что некоторые поля, относящиеся к этому пользователю, заполнены, что пользователь относится к этому типу). Любые запросы просто должны включать предложение «AND usertype =».

Если с каждым типом связано много полей или правил, то ваша идея трех таблиц является наилучшей.

Таблица ПОЛЬЗОВАТЕЛЕЙ (идентификатор, тип, имя, пароль)
GENUSERS (ID, genfield1, genfield2)
Администраторы (ID, adminfield1, adminfield2)

Все, что вам нужно - это ограничения между идентификаторами в таблице (а основная таблица USERS сохраняет идентификаторы уникальными). В большинстве ситуаций работает очень хорошо, но отчеты, которые включают пользователей обоих типов со своими конкретными полями, должны быть выполнены в двух частях (объединенный SQL или подзапросы или несколько левых объединений).

0 голосов
/ 14 апреля 2010

Две таблицы. ПОЛЬЗОВАТЕЛИ с именами пользователей, первым, последним и т. Д. РОЛИ с ролями и ссылкой на имя пользователя (или идентификатор пользователя или что-то еще) Установите уникальное ограничение на имя пользователя. Поместите рабочую станцию ​​nbr, электронную почту, телефон, все, что вам нужно, в таблицу пользователей. Поместите 2 столбца в таблицу ROLES - USERID и ROLE.

...