2014-05-22 49 views
1

如果我有一個約會網站的「用戶」表,那麼關係列可以是同一個表內另一個用戶的主鍵的外鍵?這是一對一的關係(每個人只能有一個關係夥伴)。該值可以爲空(該人目前不在關係中)?引用同一個表的外鍵......你能幫忙解釋一下這個例子嗎?

在數據庫設計中做到這一點的正確方法是什麼?

+1

您所描述的方式是正確的方式;除非你不會把它稱爲_foreign key_,因爲[a]它不是外來的,[b]它不是關鍵。它只是一個恰好與主鍵保持相同值的列。你爲什麼懷疑它?你有沒有實施它,然後遇到問題? –

+0

你的例子不清楚。你可以添加一個圖形表示 – vikeng21

+0

我只是不確定是否更合適有一個單獨的「關係」表?我沒有實現任何東西,但我想完全理解設計概念。我只是需要專家建議 – Caleb

回答

1

是的,但是你不能強制兩個人通過約束彼此鏈接。您必須確保代碼中存在這種情況。

UserA has relationship with UserB 
UserB has relationship with UserA 

UserA has relationship with UserB 
UserB has no relationship 

UserA has no relationship 
UserB has relationship with UserA 

所有這些都是有效的FKS的領域,其實......

UserA has relationship with UserB 
UserB has relationship with UserC 

UserA has relationship with UserB 
UserC has relationship with UserB 

也被允許FK。您需要確保代碼中的代碼都正確設置,並確保在更新期間進行正確的事務處理。

你也可以使關係用戶唯一,這將至少防止最後一種情況。

+0

哦,好吧!謝謝!有沒有更好的設計方法呢? – Caleb

+0

不是我能想到的。您可以確定何時更新他們的關係狀態,您是否在單個事務中執行此操作,以使其全部或全部不變。 – woot

0

你可以把任何你想要的東西放在桌子上。你給出了一個陳述/含義,並讓它成真的行進入表格。查詢的含義是它的行根據其表的含義變爲真。這就是你需要使用數據庫的全部內容。

從給定的陳述和可能出現的情況出發遵循約束條件。你宣佈他們阻止不能出現的國家。

當某些源列的值集必須是目標列值集的子集時,存在「包含依賴」約束。如果目標也必須形成其表格的關鍵字,那麼存在「外鍵」約束。目標表是否爲源表並不重要。在SQL中,有一種語法爲「外鍵」的聲明,但是因爲它的目標只是唯一而不是鍵,所以它實際上只定義了一個外鍵。某些設計方法碰巧以某些約束爲重點,而犧牲其他約束甚至表意義。

你心中有關係(不一定體現了一個表)

coupled(p,q) // == '[p] & [q] are coupled' 
    key {p,q} 
    // plus CHECK-expressible constraints only involving coupled 

嵌入該表中另一隻是意味着這些限制將適用於嵌入表的相應部分。

你還必須考慮(不一定體現在一個表)

userfact(p,...) // == '...[p] is such that ...' 
    key {p} 

如果聲明

userbig(p,...,q) // == userfact(p,...) and coupled(p,q) 
    key {p} fk q->p 
    // plus coupled-like constraints involving select p,q from userbig 

則無法錄製userfact(P,...)關於p誰不耦合。另外,您必須涉及上述select才能查詢與用戶事實無關的耦合。

如果設Q爲空,那麼你得到

usernull(p,...,q) // == userfact(p,...) and (q is null and not exists q coupled(p,q) or not q is null and coupled(p,q)) 
    key {p} 
    // plus coupled-like constraints involving select p,q from usernull where not q is null 

不幸的是,現在你必須涉及到更爲複雜的上述選擇查詢有關耦合獨立用戶的事實。此外,對應於fk q-> p的約束不再是fk約束,而是更復雜,因爲q可以爲空。另外,任何時候你想要usernull的任何部分(甚至所有),你可能必須測試q的null值,以確保你想要的行被使用。

最糟糕的是,由於SQL運算符的排序爲3VL,所以SQL運算符的行爲非常複雜,因此除了包含空值的非常簡單的查詢以外,其他所有的含義都非常複雜。它們不是表格含義的其他簡單組合。應該避免空值。

所以你真正想要的只是userfactcoupled及其fk p->userfact.p, q->userfact.p

工業上使用現有的SQL DBMS,必須不斷地選擇性能來約束非聲明性的,並在某些表中使用空值(儘可能接近查詢表達式葉刪除空值)。但首先應該正確設計。

相關問題