在 PostgreSQL 中實現 lck
, special
, item
與 org_id
或 user_id
組合唯一的約束
要實現 lck
, special
, item
這三個字段必須與 org_id
或 user_id
中的一個(但不能同時)組合唯一的約束,你需要創建以下約束:
方案1:使用兩個唯一約束 + 檢查約束
ALTER TABLE hs_charging
-- 確保 org_id 和 user_id 不同時為 NULL 且不同時有值
ADD CONSTRAINT org_or_user_check CHECK ((org_id IS NOT NULL AND user_id IS NULL) OR(org_id IS NULL AND user_id IS NOT NULL)
);-- 為 org_id 組合創建唯一約束
ALTER TABLE hs_charging
ADD CONSTRAINT unique_with_org UNIQUE (lck, special, item, org_id)
WHERE org_id IS NOT NULL;-- 為 user_id 組合創建唯一約束
ALTER TABLE hs_charging
ADD CONSTRAINT unique_with_user UNIQUE (lck, special, item, user_id)
WHERE user_id IS NOT NULL;
方案2:使用部分索引實現(更簡潔)
-- 確保 org_id 和 user_id 只能填一個
ALTER TABLE hs_charging
ADD CONSTRAINT org_or_user_check CHECK ((org_id IS NULL) <> (user_id IS NULL)
);-- 為 org_id 情況創建唯一部分索引
CREATE UNIQUE INDEX unique_with_org ON hs_charging (lck, special, item, org_id)
WHERE org_id IS NOT NULL;-- 為 user_id 情況創建唯一部分索引
CREATE UNIQUE INDEX unique_with_user ON hs_charging (lck, special, item, user_id)
WHERE user_id IS NOT NULL;
說明
CHECK
約束確保org_id
和user_id
有且只有一個有值- 兩個唯一約束/索引分別處理兩種情況:
- 當使用
org_id
時,lck
,special
,item
,org_id
組合必須唯一 - 當使用
user_id
時,lck
,special
,item
,user_id
組合必須唯一
- 當使用
- 使用
WHERE
子句的部分索引/約束可以更高效地實現這種條件唯一性
方案2使用部分索引通常更受推薦,因為它更靈活且性能更好。