Postgresql

外鍵 NULL 與空字元串的外鍵

  • November 18, 2020

這是藥品目錄表。有些有藥品品牌,有些是通用的(即他們永遠不會有品牌資訊)

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 個選項:

  1. 使用 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我已經使用藥物範例來說明我的查詢,但我想純粹從數據庫的角度了解解決方案的技術優點,即不討論哪種方法更適合醫學範例。

答案在於您的問題含糊不清:

但是,如果我想要一個獨特的醫學索引namebrand_id

您實際上並不想要“唯一索引”。你想強制執行某些規則。唯一索引是達到目的的手段;一個工具。問題是:你到底想要什麼?

您是否希望只有一個name帶有未知品牌的 a 實例?或者可以有多個實例?這取決於“未知”或“缺失”或“空”或NULL應該對您意味著什麼。

NULL 的規範含義是“未知”。我們根本不知道,這裡發生了什麼,它可能是任何東西,包括什麼都沒有''(字元串類型中的空( ),0數字類型中的)。

如果您想允許一個通用品牌,請在 中包含一個條目brand,將其稱為“通用”或“ ACME ”或其他任何名稱。我喜歡將 id 值0用於這樣一個包羅萬象的條目。

然後你的唯一索引或約束正在做它應該做的事情:只允許(name, brand_id)table 中的一個實例medicine。但是多個條目(name, NULL)仍然是可能的。brand_id NOT NULL如果你不想這樣,也設置。

最佳解決方案還取決於典型查詢和設置的詳細資訊。請務必準確記錄NULL / empty / 0 的含義以及您選擇這樣設計它的原因。在您實施它的那一刻,它可能看起來很清楚,但以後可能會令人困惑。

我在您引用的答案中添加了另一個連結:

引用自:https://dba.stackexchange.com/questions/90827