假设我有一个用户表,其中用户是特定租户的成员,他们的电子邮件是唯一索引到他们的租户的,如下所示:
User
id | tenant_id | email
1 1 person1@example.com
2 1 person2@example.com
允许此用户,因为尽管有重复的电子邮件,但他们在不同的租户:
3 2 person1@example.com
此用户被阻止,因为该电子邮件在同一租户处是重复的:
4 2 person1@example.com <--- will throw an error
我们有很多独特的索引 - 这部分很容易。
现在假装我希望能够添加一个可以访问所有租户的全局用户,但前提是该表中根本不存在该电子邮件。此外,一旦记录存在,其他任何人 - 无论是否租用 - 都将能够使用相同的电子邮件。
为清楚起见,全局用户可能只有一个空租户ID,但我们可能还会添加一个global
布尔值。
有没有办法为这个逻辑编写约束?您不能简单地使电子邮件全局受到限制,因为它们不能在租户之间重复,如果您使用空租户ID进行索引,如果有租用的用户具有相同的e,则postgres将允许未经授权的用户-mail。
我查看了排除约束和检查,但无法弄清楚如何将它们组合在一起(如果tenant_id为null,则全局唯一地约束电子邮件,并在插入任何内容时检查具有空租户ID和匹配电子邮件的记录记录)。
请不要问为什么我这样做 - 我的桌子实际上不是用户,我们已经考虑并解雇了其他架构:)
提前致谢!
答案 0 :(得分:1)
根据PostgreSQL文档,您可以创建unique partial index,这与在表上创建唯一的部分约束实际上相同:
NSNumbers
使用此技术,您可以为管理员和非管理员用户创建2个单独的唯一索引。
答案 1 :(得分:0)
您可以对两个字段使用UNIQUE约束:
create table myUsers
(
id int not null,
tenant int not null,
email varchar(200) not null,
UNIQUE(email, tenant)
);
insert into myUsers values
(1, 1, 'person1@example.com'),
(2, 1, 'person2@example.com');
insert into myUsers values
(3, 2, 'person1@example.com');
下一次插入会抛出错误:
insert into myUsers values
(4, 2, 'person1@example.com');
错误,警告:
23505:重复键值违反了唯一约束 &#34; myusers_email_tenant_key&#34;
在此处查看:http://rextester.com/AJZVI34616
问题的第二部分:
现在假装我希望能够添加一个可以访问所有租户的全局用户,但前提是该电子邮件根本不存在于表中。
一种解决方案可能是为管理员用户预留租户:
tenant = 0 <-- admin users
但UNIQUE约束允许重复的电子邮件,我建议您在此表中添加rol
字段,或者为此目的使用另一个管理员用户表。
就我而言,我们使用两个表,并且都有一个rol
字段。