[英]PostgreSQL constraint on default address
我有一個用戶表和地址表。 它們之間是 1:N 的關系(用戶可以有多個地址)。 在我的應用程序中,用戶可以 select 一個默認地址(isDefault:true)。
你能幫我寫一個 SQL 約束來確保只有一個地址被設置為特定用戶的默認地址嗎? (將新地址設置為默認地址時,約束應使以前的默認地址成為非默認地址 - isDefault: false)。
您可以創建過濾的唯一索引。
確切的設置取決於表的實際定義,但是如果您有一個address
表(其中address_id
是主鍵,而不是外鍵)並且user_id
是users
表的外鍵,您可以使用:
create unique index only_one_default_address
on address (user_id)
where is_default;
這將防止同一用戶使用兩個默認地址,但允許無限制的非默認地址。
然而,任何約束都不會更改數據,因此必須使用觸發器來實現“當將新地址設置為默認地址時,約束應使以前的默認地址成為非默認地址”的要求。
create or replace function reset_default_address()
returns trigger
as
$$
begin
if new.is_default then
update address
set is_default = false
where user_id = new.user_id;
end if;
return new;
end;
$$
language plpgsql;
create trigger trg_change_default_address
before update or insert on address
for each row
when (new.is_default)
execute procedure reset_default_address();
最簡單的解決方案是有一個單獨的 1:1 表“DefaultAddresses”,它具有唯一的 (UserId, AddressId) 索引。
作為替代方案,假設isDefault
列,您可以在Addresses
表的UserId
列(...) WHERE isDefault
上嘗試唯一索引。
自動更新只能通過自定義觸發器 function 完成。不過我建議在應用程序級別執行此操作。
您可以使用EXCLUDE
約束,使用user
和address
表 pk 和 fk 鍵。
ALTER TABLE address
ADD CONSTRAINT ex_address_is_default EXCLUDE USING gist (
user_id WITH =,
address_uid WITH =)
WHERE (isDefault IS TRUE);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.