2010-02-04 54 views
2

有一個有趣的情況:我有一個從a.name(子表)到b.name(父表)的外鍵。 b.name沒有唯一的約束,所以它可能包含重複的值。MySQL:引用兩個父項的外鍵

如果我在b.name 兩次把名字「鮑勃」,然後把它放在a.name,我不能再刪除或B表更新「鮑勃」的要麼實例。在這兩種情況下,它都會抱怨,通過刪除/更新表b中的行,將a.name鏈接到b.name的FKey將失敗。

現在,這是有道理的,但我希望能夠告訴FKey只有在表b中存在no其他實例'bob'時纔會失敗。因此,如果我在b.name中有多個'bob'實例,我可以更改/刪除除最後一個以外的任何實例。

[注意,這樣做明顯並添加上b.name唯一約束不會工作,因爲它會導致應用程序中的「未定義行爲」我沒有寫]

任何想法?

回答

2

直接從http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html

...Additionally, MySQL and InnoDB require that the referenced columns be indexed for performance. However, the system does not enforce a requirement that the referenced columns be UNIQUE or be declared NOT NULL.The handling of foreign key references to nonunique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE. You are advised to use foreign keys that reference only UNIQUE and NOT NULL keys....

所以,保持你的FKS綁獨特價值或誰的說會發生什麼?

+0

不知道我是如何錯過的。謝謝。 – dordal 2010-02-05 01:06:35

0

據我記得,外鍵應該指的是一個獨特的實體。 在你的情況下,你需要在BEFORE觸發器中實現所有的邏輯而不是使用外鍵

0

如果你在b.name中放置'bob'兩次,那麼它不再唯一標識爲表b中的行。

如果您的要求是b.name可以有重複值,那麼您的表需要使用更好的密鑰(代理鍵或複合鍵)。

除了更新/刪除問題之外,SELECT * FROM a join b on a.name = b.name等查詢也無法按預期方式工作。

+0

是的,謝謝。我最大的問題是我們整合的應用程序是由第三方編寫的,他們定義了數據庫模式。然後,我們在他們的數據庫中添加一些表格,這就是我們弄糟的地方。是的,我知道這並不理想。 :-) – dordal 2010-02-05 01:05:57

+0

幾乎每個編程任務都不理想:P – Seth 2010-02-05 01:33:46

0

雖然你的情況是遠遠沒有達到最佳,甚至建議,讓您可以像這樣的外鍵檢查:

SET FOREIGN_KEY_CHECKS = 0; 
// do your dirty work here 
SET FOREIGN_KEY_CHECKS = 1; 

你必須保持你的代碼參照完整性,你在你的描述帖子。