2012-08-31 33 views
2

讓我們假設我有一個下表:如何在mysql中允許外鍵約束0?

UID int (11) not null, FOREIGN KEY (UID) REFERENCES users(ID), 
OID int (11), FOREIGN KEY (OID) REFERENCES orders(ID), 
primary key(UID,OID) 

注意主鍵。

而且,我想允許每個用戶ID(UID)都有一個NULL的ID(OID)。

雖然設置主鍵後自動使我的OID字段NOT NULL

作爲解決方案,我正在考慮將0而不是將其標記爲無關字段。

所以,現在的問題是,是否有可能允許外鍵約束接受除指定字段的references之外的零(0)?

回答

0

UNIQUE KEY約束可以在這種情況下使用:

CREATE TABLE users (id int not null, primary key (id)); 
INSERT INTO users VALUES (1), (2), (3); 

CREATE TABLE orders (id int not null, primary key (id)); 
INSERT INTO orders VALUES (1), (2), (3); 

CREATE TABLE users_orders (uid int NOT NULL, oid int DEFAULT NULL, 
       FOREIGN KEY (uid) REFERENCES users (id), 
       FOREIGN KEY (oid) REFERENCES orders (id), 
       UNIQUE KEY (uid, oid)); 

INSERT INTO users_orders (uid) VALUES (1); 

這裏的a demo一起玩。

但請注意,您(可能)仍然可以在您的表格中插入多個specific UID - NULL組合(我假設您在此使用InnoDB)。例如,此查詢...

INSERT INTO users_orders o (uid) VALUES (1), (1); 

...也會成功(因爲它不會破壞任何現有約束)。

如果這個應該嚴格禁止,你最好使用一些虛擬價值usersorders表,以及 - 使foreign key約束你的交集表使用。

作爲一個旁註,我承認我對這種情況有點驚訝。例如,相交表通常被設計爲不具有任何可NULL的字段:例如,查詢中的LEFT(或RIGHT)JOIN應該用於包含沒有任何訂單的用戶。你能否解釋一下爲什麼這個決定(使OID爲空)被選中了?

+0

這個想法是存儲帳單信息。每個用戶都有一個默認的帳單信息,並且每個訂單也單獨存儲。如果你建議以其他方式存儲它,我會很樂意跟進... – Anonymous

+0

那麼,是什麼讓你認爲'uid'添加到'orders'表是不恰當的? )由於每個訂單(我假設)只有一個用戶分配給它。然後,查詢所有用戶和他們的訂單(包括沒有任何訂單的用戶通過'LEFT JOIN')就很容易了。 – raina77ow

+0

這是有道理的。我也可以在每個訂單中存儲結算信息。但是我想知道我會在哪裏存儲默認計費呢? – Anonymous

0

我不認爲這可能在MySQL中,但解決方法可能是在引用外部表中插入帶有0值的虛擬條目。

+0

是的,這就是我的第一個想法,但這看起來像一個骯髒的方式,因爲它實際上會影響關係並使其成爲相關領域,而理想情況下它不應該與此領域有任何關係。 – Anonymous

1

其中一種選擇是使用'代理主鍵'代替當前的PK,並在下面的組合(UID,OID)上放置一個UNIQUE約束條件 - 假設您打開代理主鍵 - 就像身份列

+0

這是一個好主意,但是當我們根據這些字段進行選擇時,是否會影響沒有主鍵的性能?它需要手動定義索引,還是可以像這樣使用它? – Anonymous

+0

您需要在UID,OID上創建一個索引,但應該考慮到您的性能問題 – InSane

+0

UNIQUE KEY(uid,oid)實際上會在這兩個字段上創建一個複合索引。 – raina77ow

0

嘗試使用UNIQUE KEY。它允許使用NULL值。