可选外键 - 这是一个很好的解决方案吗?

时间:2012-01-25 12:52:51

标签: sql-server database-design foreign-keys

我的表格中有很少的权限表:

UserId, Object Id, lot of bit fields

我已将用户组添加到我的数据库,我需要更新权限才能与用户和用户组一起使用。我想到了两种方法。

  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 - 其他将为null。 表可能如下所示:

    UserId NULL, GroupId NULL, ObjectId NOT NULL, lot of bit fields
    
  3. 您认为最佳解决方案是什么?两者的利弊是什么?还有其他更好的解决方案吗? 编辑:我需要知道如何处理用户和组的外键,而不是位字段。

2 个答案:

答案 0 :(得分:2)

如果可以授予两个集合的权限类型总是相同的,我可能会将它保存在同一个表中。但请确保添加检查约束:

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表修改为直接接受组,或者让组表(使用"仅限组"列)引用{{ 1}}表?它可能是一个更简单的路径(例如,根据数据库的其他部分只需要与用户一起工作)。然后,您的所有权限检查都可以是"这里有一个ID列表(其中一个是用户,另一个是组),请计算出该用户的聚合权限"。

答案 1 :(得分:0)

我会做第三个选项,即将你的位字段更改为tinyint(int family或varbinary中的任何内容都可以正常工作,但你可能只需要2-3个标志)并使用bitwise operators(不会转换必要的)检查安全级别。这不会添加列或表。

我通常在同一资源需要多种访问控制组合时执行此操作。例如,我将有一个名为calendar_permissions的int列,并从最低有效位视图(1),add(2),edit(4),delete(8)分配以下值。因此,如果我想检查删除权限,我会做一个“intvalue AND 8 = 1”条件。 (如果用户拥有所有权限,则该值将为15 = 8 + 4 + 2 + 1)

在您的情况下,1表示用户权限,2表示组权限,可选3表示用户和组权限。如果您对使用这种按位算术的应用程序感到不舒服,可以通过视图公开它。

因为您将2定义为组权限,所以检查“用户”权限的调用应该是兼容的,因为整数值1转换为true。

您可以选择对这些字段设置检查约束,以限制对您的应用程序有意义的值。

PRO:没有额外的列/表,与当前系统兼容。

CON:不像人类可读,有些人在按位操作方面存在问题。您可能必须创建一个视图以让任何人实际使用它。