2010-04-14 59 views
0

我有幾個實體,它們表示需要能夠登錄到特定系統的不同類型的用戶。此外,他們有不同類型的信息與他們相關聯。如何模擬這種一對一的關係?

例如:一個「普通用戶」,它有一個電子郵件地址和「管理員用戶」,它有一個工作站號碼(注意這是一個假設的情況)。兩個實體還共享公用屬性,如名字,姓氏,地址和電話號碼。最後,他們自然需要有一個(唯一的)用戶名和密碼才能登錄。

在應用程序中,用戶只需填寫他的用戶名和密碼,並且應用程序的功能會稍微改變到用戶的類型。你可以想象這個工作的用戶名必須是唯一的。

我應該如何有效地建模?

我不能只是創建兩個表,因爲那樣我就不能強制用戶名上的唯一常量。

我也不能把它們放在一張表中,因爲它們有不同類型的特定信息。

我想我可能需要3個獨立的表,一個用於用戶名(用戶名和密碼),一個用於「普通用戶」,另一個用於「管理用戶」,但這些關係如何工作?還是有另一種解決方案? (順便說一下,目標數據庫管理系統是MySQL,所以我不認爲數據庫系統本身支持泛化)。

回答

0

你的3個表的方法似乎沒問題。 在用戶表中只有ID,用戶名,密碼,usertype。 一般用戶表中有ID,UserID(來自用戶表),其他字段。 管理員用戶也一樣。

用戶類型字段將告訴您從什麼表尋找更多的信息

if(usertype==admin) 
    select * from admins where userid=:id; 
else  
    select * from general where userid=:id; 
+0

這聽起來像是要走的路。有沒有辦法從一個查詢中的2個相關表中獲取信息,或者我只限於查詢,然後是if和then另一個查詢(這沒有問題,但我只是好奇)。 – pbean 2010-04-14 13:23:30

+0

你說你在不同的表中有不同的字段 - 這使得很難將其放入單個查詢中。我不認爲你會在一個視圖中顯示兩個usertype的信息 - 所以不需要將它們組合起來 – Riho 2010-04-15 06:26:44

0

兩張表。具有用戶名,第一個,最後一個等的用戶角色,以及回到用戶名(或用戶ID或其他)的鏈接。對用戶名稱設置一個唯一的約束。將工作站nbr,電子郵件,電話,無論你需要什麼,放在用戶表中。將2列放在ROLES表中 - USERID和ROLE。

0

你應該決定被多少具體信息存儲(或可能存儲在未來),並根據該決定那。如果每個用戶類型只有少數幾個字段,那麼使用單個表就行了。

USERS表(名稱,類型,電子郵件,密碼,genfield1,genfield2,adminfield1,adminfield2)

確保包括類型(不承擔因爲一些給該用戶特定的字段都填寫該用戶是該類型的)字段。任何查詢都需要包含「AND usertype =」子句。

如果有很多字段或規則與每種類型相關,那麼你對三張表的想法是最好的。

USERS表(ID,類型,名稱,密碼)
GENUSERS(ID,genfield1,genfield2)
ADMINUSERS(ID,adminfield1,adminfield2)

桌子上的ID之間的約束是你所需要的(並且主USERS表保持這些ID唯一)。在大多數情況下工作得非常好,但包含兩種類型的用戶及其特定字段的報告必須分兩部分完成(聯合SQL或子查詢或多個左連接)。

0

可以包含適用於所有用戶和表1爲每個特定的用戶類型的信息這就是一個「一般」用戶表解決這個問題。在你的例子中,你將需要3張桌子。

用戶:此表僅保存所有用戶類型之間共享的信息,即。用戶ID,姓名,地址等

GeneralUsers:此表提供了一個引用的用戶表foreing關鍵用戶ID「延伸」的用戶表。另外,在這裏保存特定於一般用戶的信息,fx。 EmailAddress的等

AdminUsers:與GeneralUsers,該表還提供了一個外鍵用戶ID引用用戶表「延伸」的用戶表。此外,在這裏保留特定於管理員用戶的信息,fx。 WorkstationId等

通過這種方法,您可以添加額外的「特」在需要的時候通過簡單地添加新表,使用的外鍵引用「延伸」的用戶表。您也可以創建多個專業級別。例如,如果管理員用戶是普通用戶以及管理員用戶,則AdminUser可以通過使用GeneralUsers而不是用戶的前置密鑰來「擴展」GeneralUsers而不是用戶。

當你需要從這個模型retreive數據,需要的用戶類型要查詢的。例如,如果你需要查詢GeneralUser你將需要類似於:ON GeneralUsers.UserId = Users.UserId

或者,如果

SELECT * FROM GeneralUsers LEFT JOIN用戶查詢管理員用戶

SELECT * FROM AdminUsers LEFT JOIN用戶ON AdminUsers.UserId = Users.UserId

如果您有更多的專業化水平,例如讓管理員用戶也是普通用戶,您只需加入回頭路。

SELECT * FROM AdminUsers LEFT JOIN GeneralUsers ON AdminUsers.UserId = GeneralUsers.UserId LEFT JOIN用戶ON GeneralUsers.UsersId = Users.UserId

+0

這與Riho的建議方法類似。不過,我有一個問題。由於「Users」表中的所有用戶標識都是唯一的,因此在「GeneralUsers」和「AdminUsers」表中簡單地使用相同的ID是一個好主意(除了擁有自己的ID以外,還有一個名爲「 UserId「? – pbean 2010-04-14 13:24:49

0

我最肯定不會做,你有單獨的表作爲模型在GeneralUser中,AdminUser和ReadOnlyUser。

在數據庫設計中,一個很好的經驗法則是「Down beats across」。我將創建一個SystemUsers表和一個角色表,並定義一個連接表來將SystemUser置於角色中,而不是多個表(每個類型一個表)。另外,我會定義個人角色。

通過這種方式,可以將用戶添加到多個角色或從多個角色中刪除。

角色可以有多個權限,可以隨時修改。

連接到其他地方不需要GeneralUserId,AdminUserId和ReadOnlyUserId列 - 只是一個SystemUserId列。

這與基於ASP.Net角色的安全模型非常相似。

alt text http://img52.imageshack.us/img52/2861/rolebasedsecurity.jpg

+0

感謝您的洞察,但問題更多的是泛化和一對一的關係,而不是安全模型的實際實現。:) – pbean 2010-04-14 13:22:32

+0

@pbean:answer edited。 – 2010-04-14 13:37:52