在Sql中按数量限制多对多的关系

时间:2015-05-16 08:53:16

标签: mysql sql

三个表:用户,角色和数据透视表(多对多)role_user。

user:
- id
- name

role:
- id
- name

role_user
- id 
- user_id: foreign key link to user
- role_id: foreign key link to role

如果我想限制用户可以拥有的最大角色数量,例如,我可以将role_id外部链接作为role_1字段放在用户上,而不是使用多对多的数据透视表。

users:
- id
- name
- role_id_1

如果我每个用户只需要两个角色,那也是如此。

users:
- id
- name
- role_id_1
- role_id_2

如果我想使用数据透视表将数量限制为1,2或其他内容(不在用户表上使用外部角色链接),该怎么办?在sql中有一个选项吗?

类似于复合唯一索引选项,包括数据透视表中的role_id和user_id,但不是对唯一性的约束,而是对user_id出现次数限制的自定义约束。

1 个答案:

答案 0 :(得分:3)

有一种方法可以在没有触发器的SQL中实现它。这有点复杂,但你可以做到。

首先添加另一个表。我叫它RoleNumbers。对于用户的每个可能角色,此表将包含一行。因此,您可以使用所需的1,2或多个角色进行设置。

然后是联结表:

create table UserRoles (
    UserRoleId int not null auto_increment primary key,
    UserId int not null references users(user_id),
    RoleId int not null references roles(role_id),
    RoleNumber int not null references RoleNumbers(Number),
    unique (UserId, RoleId),
    unique (UserId, RoleNumber)
);

这使用我的命名约定。在连接表上使用合成密钥没有问题。

插入新记录时,您必须为尚未使用的RoleNumber分配值。因此,你得到了限制。最有效的方法是通过触发器,但这不是绝对必要的。你可以插入:

insert into UserRoles(UserId, RoleId, RoleNumber)
    select $UserId, $RoleId, coalesce(max(RoleNumber), 0) + 1
    from UserRoles
    where UserId = $UserId;

delete需要单独的查询来维护编号方案。