简体   繁体   English

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

[英]Limit many to many relationship by number in Sql

Three tables: users, roles and a pivot table (many to many) role_user. 三个表:用户,角色和数据透视表(多对多)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

If I wanted to limit the amounts of maximum roles a user can have to only 1 for example, I could put the role_id foreign link on the user as a role_1 field instead of using a pivot table of many to many. 例如,如果我想限制用户可以拥有的最大角色数量,我可以将role_id外部链接作为role_1字段放在用户上,而不是使用多对多的数据透视表。

users:
- id
- name
- role_id_1

The same goes if I wanted only two roles per user. 如果每个用户只需要两个角色,情况也是如此。

users:
- id
- name
- role_id_1
- role_id_2

What if I wanted to limit the amount to 1, 2 or something else using a pivot table (Not using foreign role links on the user table) ? 如果我想使用数据透视表将数量限制为1,2或其他内容(不在用户表上使用外部角色链接),该怎么办? Is there an option for that in sql ? 在sql中有一个选项吗?

Something like a composite unique index option including role_id and user_id in the pivot table, but instead of a constraint on the uniqueness, a custom constraint on the limit of the user_id number of appearances. 类似于复合唯一索引选项,包括数据透视表中的role_id和user_id,但不是对唯一性的约束,而是对user_id出现次数限制的自定义约束。

There is a way you can implement this in SQL without triggers. 有一种方法可以在没有触发器的SQL中实现它。 It is a bit complicated, but you could do it. 这有点复杂,但你可以做到。

It starts by adding another table. 它首先添加另一个表。 Let me call it RoleNumbers . 我称之为RoleNumbers This table would consist of one row for each possible role for a user. 对于用户的每个可能角色,此表将包含一行。 So, you set it up with 1, 2, or however many roles you want. 因此,您可以使用所需的1,2或多个角色进行设置。

Then for the junction table: 然后为联结表:

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)
);

This uses my naming conventions. 这使用我的命名约定。 I have no problem with having a synthetic key on a junction table. 在连接表上使用合成密钥没有问题。

When you insert a new record, you would have to assign a value to RoleNumber that is not already being used. 插入新记录时,必须为尚未使用的RoleNumber分配值。 Hence, you get the limit. 因此,你得到了限制。 The most efficient way to do this is via triggers, but that is not strictly necessary. 最有效的方法是通过触发器,但这不是绝对必要的。 You could do an insert as: 您可以执行以下插入:

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

delete would require a separate query for maintaining the numbering scheme. delete将需要单独的查询来维护编号方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM