外键和一个条件的T-SQL约束

时间:2015-01-23 13:57:30

标签: sql sql-server tsql

我正在尝试设置一个小型数据库来组织权限。我正在使用这四个表:

  • User,列:UserID,名称
  • UserGroup,列:UserGroupID,名称
  • UserGroupUsers,列:UserID,UserGroupID
  • Permission,列:PermissionID,UserID,UserType,Permission,PermissionValue

规则:

  • 一个用户可以分为多个组
  • 一个群组可以拥有多个用户
  • 权限可以是用户的一部分,也可以是用户组的一部分。

现在我正在尝试设置约束,每当我删除useruserGroup时,我也想删除带有数据库约束的Permission行。

useruserGroup的关系如下:

User中的一行可以在Permissions中包含多行但具有额外条件:UserType = 1

小组的相同:

UserGroup的一行可以在Permissions中有多行,但附加条件为UserType = 2

示例:

表:权限:

PermissionID   |   UserID   | UserType | Permission | PermissionValue
---------------------------------------------------------------------
1                  1          1          MainMenu      15
2                  1          2          MainMenu      2

第1行表示user = user = 1

的用户权限

第2行表示usergroupID = 1的用户组的userGroup-permission。

到目前为止我尝试了什么:

ALTER TABLE dbo.permissions 
  ADD CONSTRAINT fk_permissionsAccounts 
  FOREIGN KEY(userID) 
  REFERENCES dbo.users(userID) 
    ON UPDATE CASCADE 
    ON DELETE CASCADE 

但这个实际上是错误的,因为它应该只发生在UserType = 1

我接下来尝试的是向UserTypeUsers两个表添加一列Groups,包括类型,但是我收到了消息:

  

该字段不是密钥的一部分。

此尝试的来源:

ALTER TABLE dbo.permissions 
   ADD CONSTRAINT fk_permissionsAccounts 
   FOREIGN KEY(userID, accountType)
   REFERENCES dbo.users(userID, accountType) 
       ON UPDATE CASCADE 
       ON DELETE CASCADE 

我正在使用SQL Server 2008

我对任何建议都很满意。提前谢谢。

编辑解决方案:

我编辑了表格:

Permission,列:PermissionID,UserID,UserGroupID,Permission,PermissionValue。

我在null-allowedUserID都设置了UserGroupID属性,但添加了一个检查约束,只允许填充其中一个字段,其他字段必须为null:

ALTER TABLE dbo.permissions
WITH CHECK ADD  
CONSTRAINT chk_permissions
CHECK  (
       ([AccountID] IS NULL AND [AccountGroupID] IS NOT NULL) OR 
       ([AccountID] IS NOT NULL AND [AccountGroupID] IS NULL)
        )

现在我可以添加默认约束:

ALTER TABLE dbo.permissions 
  ADD CONSTRAINT fk_permissionsUsers
  FOREIGN KEY(userID) 
  REFERENCES dbo.users(userID) 
    ON UPDATE CASCADE 
    ON DELETE CASCADE 

ALTER TABLE dbo.permissions 
  ADD CONSTRAINT fk_permissionsUserGroups
  FOREIGN KEY(userGroupID) 
  REFERENCES dbo.usergroups(userGroupID) 
    ON UPDATE CASCADE 
    ON DELETE CASCADE 

1 个答案:

答案 0 :(得分:2)

你能改变一下桌面设计吗?如果将UserGroupId添加到Permission表中,那么这将变得更加简单。不需要UserType列(当然,除非您需要它)。权限表中的行将 一个UserId 一个UserGroupId,但不是两者(检查约束可以强制执行此操作)。

另外,如@Damien_The_Unbeliever所述,使用名为UserId的列来保存UserId或UserGroupId并不理想。如果必须这样做,请更改列的名称以防止混淆。