2013-09-23 73 views
0

我想知道存儲我的用戶和他們的組在3個表與2個表中的優點和缺點。 2個表用戶和組:3或2表(SQL)

  1. 組的

    優點很容易僅僅是用戶自己,似乎在大多數情況下共享所有相同的域用戶,即,名稱,圖片,密碼,電子郵件。 3個表

    1. 有一個3 groups表會更明確,從而這可能是開發者更容易理解

    優點/維持。

缺點3個表 1.通過不執行#1在上述「2代表的優點」違反跨應用程序代碼DRY原則。

我還應該考慮什麼?

2個必填表格是users表格和group_member表格。

+---------+  +------------+ 
| users |  | group_member |  +----------+ 
+---------+  +------------+  | groups | 
| user_id |----->| user_id |  +----------+ 
| name |  | group_id |<----| group_id | 
| pass |  +------------+  | name  | 
| ...  |       | ...  | 
+---------+       +----------+ 

            **theoretical 3rd table** 

注:user_id,並在group_membergroup_id都希望能 指user_idusers

+1

這完全取決於你期望你的應用程序現在和不久的將來做什麼。雖然我會傾向於在正常化方面犯錯。 –

+0

@MikeBrant謝謝,你能提供一些例子,也許在答案?關於這個問題的思考對我來說很新,所以我甚至不知道什麼是可能的。 –

+0

標記爲偏離主題將被遷移到[dba.se] – hjpotter92

回答

3

要點:如果您想將用戶羣&存儲在一張表中,因爲它們共享(大多數)特徵,這是非常有效的。但是,這意味着在技術上一個組可以是用戶的成員,並且您不能在數據庫級別強制用戶可以在組中而不是其他人擔心:

1個表中的情景:

CREATE TABLE users_and_groups (id int... 
CREATE TABLE group_members (
    group_id, 
    user_id 
    FOREIGN KEY (group_id) REFERENCES users_and_group (id) -- no way to limit on only groups 
    FOREIGN KEY (user_id) REFERENCES users_and_group (id) -- no way to limit on only users 
) 

方案在2個表:

CREATE TABLE users (id int... 
CREATE TABLE groups (id int... 
CREATE TABLE group_members (
    group_id, 
    user_id 
    FOREIGN KEY (group_id) REFERENCES groups (id) -- guarantees a group 
    FOREIGN KEY (user_id) REFERENCES users (id) -- guarantees a user 
) 

防守建立一個數據庫,這樣可以防止一大堆的傷害,如果在應用程序級別的錯誤出現。


但是,如果user & group實體共享大量數據(既可以例如自己的其他對象,有個人資料頁等),4臺解決方案可以進行得很順利:

CREATE TABLE users_and_groups (id, ...shared data... 
CREATE TABLE users (users_and_groups_id, ...user specific data... 
CREATE TABLE groups (users_and_groups_id, .. group specific data... 
CREATE TABLE group_members (
    group_id, 
    user_id 
    FOREIGN KEY (group_id) REFERENCES groups (users_and_groups_id) -- guarantees a group 
    FOREIGN KEY (user_id) REFERENCES users (users_and_groups_id) -- guarantees a user 
) 

這有幾個優點:

  • 外鍵的情形之一的組或用戶allowd可以在1列。
  • 在應用程序級別,這是經典遺傳:基座users_and_groups,並且兩個user & group延伸基類/表。
  • 強制執行組或用戶仍然可以使用外鍵
  • 如果用戶或組獲得特定數據,則不需要將列添加到對大部分記錄無用的表中,可以存儲在類型特定的表中。

一些缺點:

  • 就不可能執行該實體可以是一個用戶或一組,但不兩者(類型更少)
  • 除非你存儲冗餘列type(或is_group/is_user),確定一個實體是一個組還是一個用戶需要一個JOIN,但由於這是在雙方的主鍵上,開銷應該很小
+0

- @ Wrikken,謝謝。在'users_and_groups'表中只有一個布爾型的'is_group'字段呢?我試圖權衡您提到的假定錯誤的成本與擁有可識別所有帳戶(用戶+組)的單個自動遞增主鍵的成本。對於每個賬戶都有一個號碼似乎是理想的。 –

+0

您可以添加'is_group',但這並不會改變您在此時無法強制執行'group_members'表的完整性的情況。沒有'REFERENCES users_and_groups(id)WHERE is_group = 1'的語法。你認爲你可以從單一身份證得到什麼優點? – Wrikken

+0

還有一個選項,它涉及4個表格,但是_can_在某些情況下可以很好地工作:'user_and_groups(id,...共享數據...),用戶(id_from_users_and_groups,...特定用戶數據... ),groups(id_from_users_and_groups,...特定組數據...),group_members(group_id,user_id,FOREIGN KEY group_id REFERENCES groups(id_from_users_and_groups),FOREIGN KEY user_id REFERENCES user(id_from_users_and_groups)'。類的類和繼承類: 'users'&'groups' each_extend_'users_and_groups' data,and still can enforce integrity and keep your single id。 – Wrikken

2

如果有的話,我想group_member將是可選的表。你最好只這個表,如果你需要用戶之間的許多一對多關係。換句話說,如果一個用戶可以屬於多個組,那麼您需要一個可以將user_id鏈接到group_id的表。如果用戶只能屬於一個,你可能仍然一個groups表,然後對usersgroup_id列。

但是,要回答您原來的問題,如果您將組信息(如組名稱)存儲在group_member表中,則必須爲該組內的每個用戶重複此數據。你會有許多具有相同組名稱的行,如果你想要稍後更改組名稱,則必須更新許多行而不是僅更新一行。這也使得很難分辨同一組中的誰,並且很多這類查詢會變得非常低效。

無論您是使用一個還是兩個表格,將不同的組標準化爲單個groups表格絕對是正確的方法。

+0

- @ MikeChristensen,謝謝。我在想的是,組名將被存儲在用戶表中,因爲對於組group_id = user_id。該組本身就是一個用戶。這是否改變你的觀點? –

+0

不,我仍然會將這些組標準化到他們自己的表格中。這樣,您可以在組上存儲各種元數據,並將一個或多個用戶鏈接到這些組。在關係數據庫中,規則是儘量減少冗餘。 –