T-SQL 外键约束和一个条件
T-SQL Constraint on Foreign Key and one Condition
我正在尝试建立一个小型数据库来组织权限。我正在使用这四个 tables:
User
,列:用户 ID,名称
UserGroup
,列:UserGroupID,名称
UserGroupUsers
,列:用户 ID、用户组 ID
Permission
,列:PermissionID、UserID、UserType、Permission、PermissionValue
规则:
- 一个用户可以在多个组中
- 一个群组可以有多个用户
- 权限可以是用户的一部分,也可以是用户组的一部分。
现在我正在尝试设置一个约束,每当我删除 user
或 userGroup
时,我还想删除具有数据库约束的 Permission
行。
user
和userGroup
的关系如下:
User
的一行可以在 Permissions
中包含多行,但有额外的条件:UserType = 1
。
组相同:
UserGroup
的一行可以在 Permissions
中包含多行,但有额外的条件 UserType = 2
。
示例:
Table:权限:
PermissionID | UserID | UserType | Permission | PermissionValue
---------------------------------------------------------------------
1 1 1 MainMenu 15
2 1 2 MainMenu 2
第 1 行表示 userID = 1 的用户的用户权限
第 2 行表示用户组 ID = 1 的用户组的用户组权限。
到目前为止我尝试了什么:
ALTER TABLE dbo.permissions
ADD CONSTRAINT fk_permissionsAccounts
FOREIGN KEY(userID)
REFERENCES dbo.users(userID)
ON UPDATE CASCADE
ON DELETE CASCADE
但这一个实际上是错误的,因为它应该只发生在 UserType=1
我尝试的下一件事是向 tables Users
和 Groups
添加一列 UserType
,包括类型,但我得到了消息:
the field is not part of a key.
本次尝试的来源:
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
我很乐意接受任何建议。提前致谢。
编辑解决方案:
我编辑了 table:
Permission
,列:PermissionID、UserID、UserGroupID、Permission、PermissionValue。
我已经在两个 UserID
和 UserGroupID
上设置了 null-allowed
属性,但添加了一个检查约束,它只允许填充两个字段之一,其他字段必须为空:
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
你能稍微改变一下 table 的设计吗?如果您将 UserGroupId 添加到 Permission table 中,那么这将变得更加简单。不需要 UserType 列(当然,除非您想要它)。 Permission table 中的行将具有 一个 UserId 或 一个 UserGroupId,但不能同时具有两者(检查约束可以强制执行此操作)。
此外,如@Damien_The_Unbeliever 所述,使用名为 UserId 的列来保存 UserId 或 UserGroupId 并不理想。如果您必须这样做,请更改列的名称以防止混淆。
我正在尝试建立一个小型数据库来组织权限。我正在使用这四个 tables:
User
,列:用户 ID,名称UserGroup
,列:UserGroupID,名称UserGroupUsers
,列:用户 ID、用户组 IDPermission
,列:PermissionID、UserID、UserType、Permission、PermissionValue
规则:
- 一个用户可以在多个组中
- 一个群组可以有多个用户
- 权限可以是用户的一部分,也可以是用户组的一部分。
现在我正在尝试设置一个约束,每当我删除 user
或 userGroup
时,我还想删除具有数据库约束的 Permission
行。
user
和userGroup
的关系如下:
User
的一行可以在 Permissions
中包含多行,但有额外的条件:UserType = 1
。
组相同:
UserGroup
的一行可以在 Permissions
中包含多行,但有额外的条件 UserType = 2
。
示例:
Table:权限:
PermissionID | UserID | UserType | Permission | PermissionValue
---------------------------------------------------------------------
1 1 1 MainMenu 15
2 1 2 MainMenu 2
第 1 行表示 userID = 1 的用户的用户权限
第 2 行表示用户组 ID = 1 的用户组的用户组权限。
到目前为止我尝试了什么:
ALTER TABLE dbo.permissions
ADD CONSTRAINT fk_permissionsAccounts
FOREIGN KEY(userID)
REFERENCES dbo.users(userID)
ON UPDATE CASCADE
ON DELETE CASCADE
但这一个实际上是错误的,因为它应该只发生在 UserType=1
我尝试的下一件事是向 tables Users
和 Groups
添加一列 UserType
,包括类型,但我得到了消息:
the field is not part of a key.
本次尝试的来源:
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
我很乐意接受任何建议。提前致谢。
编辑解决方案:
我编辑了 table:
Permission
,列:PermissionID、UserID、UserGroupID、Permission、PermissionValue。
我已经在两个 UserID
和 UserGroupID
上设置了 null-allowed
属性,但添加了一个检查约束,它只允许填充两个字段之一,其他字段必须为空:
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
你能稍微改变一下 table 的设计吗?如果您将 UserGroupId 添加到 Permission table 中,那么这将变得更加简单。不需要 UserType 列(当然,除非您想要它)。 Permission table 中的行将具有 一个 UserId 或 一个 UserGroupId,但不能同时具有两者(检查约束可以强制执行此操作)。
此外,如@Damien_The_Unbeliever 所述,使用名为 UserId 的列来保存 UserId 或 UserGroupId 并不理想。如果您必须这样做,请更改列的名称以防止混淆。