簡體   English   中英

PostgreSQL 默認地址約束

[英]PostgreSQL constraint on default address

我有一個用戶表和地址表。 它們之間是 1:N 的關系(用戶可以有多個地址)。 在我的應用程序中,用戶可以 select 一個默認地址(isDefault:true)。

你能幫我寫一個 SQL 約束來確保只有一個地址被設置為特定用戶的默認地址嗎? (將新地址設置為默認地址時,約束應使以前的默認地址成為非默認地址 - isDefault: false)。

您可以創建過濾的唯一索引。

確切的設置取決於表的實際定義,但是如果您有一個address表(其中address_id是主鍵,而不是外鍵)並且user_idusers表的外鍵,您可以使用:

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約束,使用useraddress表 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM