[英]Postgres conditional unique constraint
假設我有一個用戶表,其中用戶是特定租戶的成員,他們的電子郵件是唯一索引到他們的租戶,如下所示:
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將允許未經授權的用戶-郵件。
我查看了排除約束和檢查,但無法弄清楚如何組合它們(如果tenant_id為null,則全局唯一地約束電子郵件,並在插入任何記錄時檢查具有空租戶ID和匹配電子郵件的記錄)。
請不要問為什么我這樣做 - 我的桌子實際上不是用戶,我們已經考慮並解雇了其他架構:)
提前致謝!
根據PostgreSQL文檔,您可以創建唯一的部分索引 ,這與在表上創建唯一的部分約束實際上相同:
CREATE UNIQUE INDEX some_index ON some_table (col_a) WHERE (col_b is null);
使用此技術,您可以為管理員和非管理員用戶創建2個單獨的唯一索引。
您可以對這兩個字段使用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:重復鍵值違反唯一約束“myusers_email_tenant_key”
請在此處查看: http : //rextester.com/AJZVI34616
對於問題的第二部分:
現在假裝我希望能夠添加一個可以訪問所有租戶的全局用戶,但前提是該表中根本不存在該電子郵件。
一種解決方案可能是為管理員用戶預留租戶:
tenant = 0 <-- admin users
但UNIQUE約束允許重復的電子郵件,我建議您在此表中添加rol
字段,或者為此目的使用另一個admin用戶表。
在我的例子中,我們使用兩個表,並且都有一個rol
字段。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.