Дополнительные внешние ключи - это хорошее решение? - PullRequest
1 голос
/ 25 января 2012

У меня есть БД с несколькими таблицами разрешений в форме:

UserId, Object Id, lot of bit fields

Я добавил группы пользователей в свою БД, и мне нужно обновить разрешения для работы с пользователями и группами пользователей. Я думаю о 2 подходах.

  1. Создать копию каждой таблицы разрешений и иметь 2 таблицы для каждого разрешения объекта (разрешения пользователя и группы) - в каждой таблице у меня будет один внешний ключ для таблиц «владельца разрешения» (в одной таблице - для пользователей и во второй таблице для групп пользователей):

    UserId NOT NULL, Object Id NOT NULL, lot of bit fields  
    GroupId NOT NULL, Object Id NOT NULL, lot of bit fields
    
  2. Добавьте одно поле (GroupId) в каждую таблицу разрешений и используйте одно из полей (UserId или GroupId), чтобы определить, является ли это разрешением для группы или пользователя. Таким образом, у меня будет таблица с 2 внешними ключами - для пользователей и групп пользователей, но для каждой записи будет использоваться только один из этих FK - другой будет нулевым. Таблица может выглядеть так:

    UserId NULL, GroupId NULL, ObjectId NOT NULL, lot of bit fields
    

Какое, на ваш взгляд, лучшее решение? Каковы плюсы и минусы обоих? Есть ли другое, лучшее решение?
РЕДАКТИРОВАТЬ: мне нужно знать, что делать с внешними ключами для пользователей и групп, а не с битовыми полями.

Ответы [ 2 ]

2 голосов
/ 27 января 2012

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

UserId int NULL,
GroupId int NULL,
constraint CK_CorrectFKs CHECK (
   (UserId is null and GroupId is not null) or
   (UserId is not null and GroupId is null)
),
ObjectId int NOT NULL, lot of bit fields

Или вы рассматривали группы моделирования как пользователей - либо просто изменили таблицу Users для непосредственного принятия групп, либо добавили таблицу групп (с "группой"только столбцы) ссылающиеся на таблицу Users?Это может быть более простой маршрут (в зависимости от того, какие другие части вашей базы данных должны работать только с пользователями, например).Тогда все ваши проверки разрешений могут быть просто «Вот список идентификаторов (один из которых пользователь, а другой - группы), пожалуйста, определите совокупные разрешения для этого пользователя».

0 голосов
/ 25 января 2012

Я бы сделал третий вариант, который изменил бы ваши битовые поля на tinyint (все в семействе int или varbinary также работало бы, но вам, вероятно, нужно всего 2-3 флага) и использовал бы битовые операторы ( преобразование не потребуется) для проверки уровня безопасности. Это не добавит столбцы или таблицы.

Обычно я делаю это, когда есть несколько комбинаций контроля доступа, необходимых для одного и того же ресурса. Например, у меня есть столбец int с именем calendar_permissions и я присваиваю следующие значения от наименьшего к наиболее значимому биту: view (1), add (2), edit (4), delete (8). Поэтому, если бы я хотел проверить разрешения на удаление, я бы выполнил условие «intvalue AND 8 = 1». (если бы у пользователя были все разрешения, значение было бы 15 = 8 + 4 + 2 + 1)

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

Поскольку вы определяете 2 как групповое разрешение, ваши вызовы для проверки разрешения «пользователь» должны быть обратно совместимыми, поскольку целочисленное значение 1 приводит к значению true.

При желании вы можете наложить ограничения на эти поля, чтобы ограничить значения, которые имеют смысл для вашего приложения.

PRO: нет дополнительных столбцов / таблиц, обратно совместимых с текущей системой.

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

...