2013-10-18 8 views
2

我正在設計一個數據庫,並且有關如何使私有某些用戶數據的問題。DB設計:如何指示列數據是公有還是私有

我有一個用戶表,其中包含名稱,城市,生日,傳記等。用戶可以將一些數據私人化(其他用戶可以看到該數據)。

首先,我想添加列到表中以指示列是否是私有的。例如:

User 
------- 

user_id | name | city | cityIsPrivate | birthday | birthdayIsPrivate 
---------+------+------+---------------+----------+------------------ 

或者,另一種方法是增加一個VARCHAR列,表示這列私營:

User 
------- 

user_id | name | city | birthday | privateColumns 
---------+------+------+----------+--------------- 

這privateColumns都會有這樣的:"city:NO; birthday:YES"

用戶表將只有三列可以是私人或公共的。我只需要在表中添加三列。

有什麼建議嗎?

+1

用'user_id'和字段(varchar)創建一個額外的表格PublicFields。帶'user_id'的'FK'。這樣你可以很容易地擴展字段的數量,而不需要額外的編碼 – DarkBee

+0

我喜歡@DarkBee提出的方法。必須解析privateColumns字段的想法似乎並不理想。另一張桌子是爲了! – Michael

+0

@DarkBee感謝您的評論。而且,我需要在另一張桌子上儲存什麼?公共專欄的名稱? – VansFannel

回答

2

如果每次查詢主表時不得不將數據移動到單獨的表中,

布爾(或等同物)的列,以指示隱私可以在其上施加的隱私設置的每一列:

  1. 是非常簡單的補充。
  2. 幾乎沒有空間。
  3. 查詢起來要快得多。
  4. 顯示隱私設置是用戶數據的固有部分。
  5. 從模式中消除不必要的複雜性。

這些與其他列相關的事實以及它們代表一種邏輯對象只是一種分心。去簡單,性能和邏輯的正確性。

1

移動你的列表私密列蒙山三個字段單獨的表,如:

UserId |ColumnName |IsPrivate 
----------------------------- 

然後你就可以與該表加入您的疑問並得到正確的結果爲每個用戶設置,並在同一時間改變用戶表的列。

如果你的用戶表不會想有變化,最好是專用的列移到列表的你單獨的表與適當的結構,像這樣:

UserId |cityIsPrivate |birthdayIsPrivate 
---------------------------------------- 

然後你就可以用加入您的用戶表在單個查詢中獲取此表並獲取您需要的結果集。

但是不要把它放在同一張桌子上。第一種方法爲您的數據庫結構提供冗餘。在第二種情況下,您將無法通過IsPrivate標準進行SELECT查詢。

+0

如果您有十列檢查隱私設置,則此第一種方法是否不會導致連接到單獨的三列表十次?這似乎與實體 - 屬性 - 值模式有很大不同,實體 - 屬性 - 值模式非常難以查詢,並且在實踐中非常麻煩 –

+0

@DavidAldridge是的,第一種方法是難以實現的方法。但它提供了一個很大的優勢 - 結構獨立性。對於某些解決方案而言,它非常必要我們可以與PIVOT和UNPIVOT一起玩,以簡化結果的工作。如果我們可以允許並使用消費者端連接邏輯,那麼我們可以返回兩個表並將它們輕鬆地鏈接到結果集合,因此不需要十個連接。但正如你在答案中看到的那樣,建議採用第二種方法,因爲它更容易。 – Alex

+0

我真的沒有把數據分成兩個表的好處。更多的約束,更多的表格,更復雜的查詢,更多的連接,更高的I/O,更高的內存使用率,更低的緩存效率......無論如何,這些好處我都不清楚,但它們似乎並沒有彌補這些缺點。除此之外,使用這兩個數據集非常緊密,以至於將它們分開對我來說沒有任何意義。 –

1

你可以有一個單獨的表(UserPrivateFields,例如)列出用戶ID與他們選擇做私募,像這樣字段一起:

UserID | PrivateField 
-------+------------- 
1  | Name 
1  | City 
2  | Birthday 

當你正在運行的程序抓取用戶信息被請求信息的人拉,你就可以建立這樣的查詢(假設所需的用戶的用戶名被傳遞到PROC):

CREATE TABLE #PublicUserFields (Publicfield varchar(50)) 
INSERT INTO #PublicUserFields (Publicfield) 
SELECT Publicfield 
FROM userPublicfields 
WHERE userid = @userid 

Declare @sql VARCHAR(MAX) = 'SELECT ' 
WHILE EXISTS (SELECT 1 FROM #PublicUserFields) 
BEGIN 
    DECLARE @Publicfield VARCHAR(50) = 
     (SELECT TOP 1 Publicfield FROM #PublicUserFields) 
    SET @sql = @SQL + @Publicfield 
    IF (SELECT COUNT(*) FROM #PublicUSERFIELDS) > 1 
    BEGIN 
     SET @SQL = @SQL + ', ' 
    END 

    DELETE FROM #PublicUserFields 
    WHERE Publicfield = @Publicfield 
END 

SET @SQL = @SQL + ' FROM MainTable WHERE userID = @userID' 

EXEC(@SQL) 

我使用動態SQL困擾的原因是您的公共字段的名稱不能直接加入通過此設置,主列表的名稱 - 只能選擇或連接到具有相同字符串值的其他記錄。你也許可以通過加入sys.columns並用列的object_id做有趣的事情來解決這個問題,但這似乎並不比這個方法簡單得多。

這很有意義,如果用戶都可以動態設置他們希望被其他人查看的字段。如果私有字段是已知的並且是靜態的,那麼您可能只想將這兩個類別分開,並強制降低私有表上讀取訪問的權限。

+0

感謝您的答案。哇! – VansFannel

+0

如果比較使單獨表格工作所需的代碼與主工作表上mkae屬性所需的代碼相比較,後者的簡單性不是避免單獨表格的參數嗎? –

相關問題