外鍵 NULL 與空字元串的外鍵
這是藥品目錄表。有些有藥品品牌,有些是通用的(即他們永遠不會有品牌資訊)
CREATE TABLE medicine ( id serial PRIMARY KEY, name text NOT NULL, brand_id integer CONSTRAINT brand_fk FOREIGN KEY (brand_id) REFERENCES brand (id) ); CREATE TABLE brand ( id serial PRIMARY KEY, name text NOT NULL );
對於儲存仿製藥,例如
abc
&xyz
,有 2 個選項:
- 使用 NULL 作為外鍵
brand_id
INSERT INTO medicine (name, brand_id) VALUES ('abc', NULL)
INSERT INTO medicine (name, brand_id) VALUES ('xyz', NULL)
2. 在品牌名稱中僅插入 1 個空字元串,並將其用於所有仿製藥的品牌 ID
INSERT INTO brand (id, name) VALUES (1, '')
INSERT INTO medicine (name, brand_id) VALUES ('abc', 1)
INSERT INTO medicine (name, brand_id) VALUES ('xyz', 1)
從我在 StackExchange 上讀到的內容來看,這似乎
1
是執行此操作的一般方式。但是,如果我想要一個關於藥物名稱和品牌 ID 的唯一索引,我將不得不使用部分索引(即 2 個索引分別在哪裡brand_id IS NULL
&brand_id is NOT NULL
)。如果我採用第二種方法,我可以用一個索引來實現它。
這些方法中的任何一種是否還有其他優點/缺點。我覺得第二種方法是非正常的,可能會有一些我以後會發現的麻煩。
PS我已經使用藥物範例來說明我的查詢,但我想純粹從數據庫的角度了解解決方案的技術優點,即不討論哪種方法更適合醫學範例。
答案在於您的問題含糊不清:
但是,如果我想要一個獨特的醫學索引
name
和brand_id
…您實際上並不想要“唯一索引”。你想強制執行某些規則。唯一索引是達到目的的手段;一個工具。問題是:你到底想要什麼?
您是否希望只有一個
name
帶有未知品牌的 a 實例?或者可以有多個實例?這取決於“未知”或“缺失”或“空”或NULL
應該對您意味著什麼。NULL 的規範含義是“未知”。我們根本不知道,這裡發生了什麼,它可能是任何東西,包括什麼都沒有
''
(字元串類型中的空( ),0
數字類型中的)。如果您想允許一個通用品牌,請在 中包含一個條目
brand
,將其稱為“通用”或“ ACME ”或其他任何名稱。我喜歡將 id 值0
用於這樣一個包羅萬象的條目。然後你的唯一索引或約束正在做它應該做的事情:只允許
(name, brand_id)
table 中的一個實例medicine
。但是多個條目(name, NULL)
仍然是可能的。brand_id NOT NULL
如果你不想這樣,也設置。最佳解決方案還取決於典型查詢和設置的詳細資訊。請務必準確記錄NULL / empty / 0 的含義以及您選擇這樣設計它的原因。在您實施它的那一刻,它可能看起來很清楚,但以後可能會令人困惑。
我在您引用的答案中添加了另一個連結: