Я подозреваю, что мне также может понадобиться таблица соединений PermissionsInRoles.
как один для PermissionsInUsers?
Ну, вы уже сказали, что одним из требований было "Каждая роль имеет фиксированный набор разрешений". Таким образом, чтобы выполнить это требование, вам необходимо сохранить разрешения, применимые к каждой роли.
Table: role_permissions
PK: (Role, Permission)
Role Permission
--
User Create
User Update
Admin Create
Admin Update
Admin Delete
Вам не нужно две разные таблицы для реализации этого требования.
К тому же, вы уже сказали: «У каждого пользователя могут быть дополнительные разрешения, не предоставляемые их ролями». Чтобы выполнить это требование, вы должны хранить пользовательские разрешения.
Table: user_permissions
PK: (username, permission)
username permission
--
user1 Rename
user1 Leak to News of the World
user2 Randomly corrupt data
Итак, опять же, вам не нужны две разные таблицы для реализации этого требования. Обе эти таблицы в 5NF.
Но это просто смешно, не так ли?
Что смешного?
- Что у вас очень сложные требования к разрешениям?
- Что вы храните бизнес-данные (например, разрешения) в таблицах?
- Что требуется более одной таблицы для моделирования ваших требований к разрешениям?
- Что-то еще?
Если вам нужен конкретный совет относительно ваших реальных таблиц, отредактируйте свой вопрос и вставьте DDL для своих таблиц.
Позже
Я посмотрел на вашу диаграмму. Не каждой таблице нужен идентификационный номер; Идентификационные номера не имеют ничего общего с нормализацией.
Если бы я проектировал вашу систему, я бы, вероятно, не использовал номера идентификаторов в таблицах Roles, Permissions и UserTypes, пока не увидел проблему с производительностью, которую можно исправить с помощью номеров id. (В большинстве систем за последние 30 лет это означает, ну, почти никогда.) Прежде чем я использовал идентификационный номер, я бы также рассмотрел и протестировал использование удобочитаемого кода. Читаемые человеком коды часто не требуют соединений; Идентификационные номера всегда требуют соединений.
В большинстве баз данных SQL вы можете комбинировать тип данных и проверять ограничение в операторе CREATE DOMAIN
. В PostgreSQL вы можете использовать что-то подобное, чтобы уменьшить количество таблиц.
CREATE DOMAIN role AS VARCHAR(7) NOT NULL
CHECK (VALUE in ('Admin', 'User', 'Guest'));
Вслед за
CREATE TABLE user_roles (
user_id integer not null references users (id),
role_name role
);
Замена таблицы оператором CREATE DOMAIN
наиболее полезна, когда число строк стабильно и относительно мало. Лично я бы предпочел таблицы.
Если вы придерживаетесь идентификационных номеров, вам также нужны уникальные ограничения для Roles.RoleName, Permissions.Description и UserTypes.UserType.
В остальном у вас вроде все нормально.