我們該如何設計資料庫(一)

2021-08-26 21:13:56 字數 3452 閱讀 4198

資料庫該如何設計,一直以來都是乙個仁者見仁智者見智的問題。

對於某一種資料庫設計,並不能簡單的用好與不好來區分。或許真的應了那句話,沒有最好,只有最適合。討論某種資料庫設計的時候,應該在某種特定的需求環境下討論。

下面來討論一下在專案中經常碰到的使用者的****儲存的問題。

我在這裡套用之前網路上流行「普通——文藝——二逼」的分類方式來描述我下文中提及的三種資料庫設計思路,並且通過查詢資料(對資料增刪改,三種設計要付出的**成本都差不多)和資料庫面臨需求變動兩個方面來思考這三種設計各有怎樣的優劣。

普通青年:

或許我們都這樣設計過資料庫

學生表 tb_student:

name

varchar(100)

名字telphone

varchar(200)

聯絡**

email

varchar(200)

***fax

varchar(200)

傳真這應該是最容易想到的一種思路,簡單、明了。

比如說我要查詢某個人的****,那麼我只用一條語句就能實現:

select

name,telphone,email,fax from

表 where

條件

在查詢的時候,這種資料庫設計十分清晰,沒有任何思維的難度,沒有任何邏輯的挑戰。但是當面臨需求變動的時候,那將會是一場災難。

比如現在要新增一類使用者:校長。那麼我們要如何處理?

答案是:再加一張表 tb_headmaster。

事實上,再加一張表其實修改並不大,因為我們完全不需要修改學生表的儲存邏輯,換句話說,這種設計是遵循了開閉原則的

但如果學生要新增一種****homephone的時候,災難發生了

怎麼辦?

在tb_student中加一列homephone?這意味著至少 要修改整個model層(或者說dal層),這種改動是十分巨大的,而且容易造成錯誤。

或者再建一張表tb_student2,來儲存homephone,然後以id來關聯兩張表?按改動規模來說,這種改動相對簡單而且不容易出錯,但是在今後的維護中會增加邏輯成本。當你一而再再而三的以這樣的方式來應對需求變動的時候,你的程式將變得不可理解。

文藝青年:

userrole

int對應使用者型別(none = 0, student = 1, teacher = 2, headmaster = 4)

ownerid

int對應使用者id

contactmethod

int****(none = 0, email = 1, homephone = 8, workphone = 16,mobilephone = 32,fax=64)

contactinfo

varchar(255)

聯絡資訊

這種是乙個多對多關係。當我們要查詢某個使用者對應的****的時候,那是一場邏輯上的浩劫:

select

contactinfo from

表 where

userrole=

某種使用者型別 and

ownerid=

某使用者id

這種寫法是一次性取出某個使用者所有的****,包括email,homephone,workphone等,之後我們可以在程式中判斷contactmethod的型別,將具體的****加以區分。你可以簡單的想到用switch-case的寫法,類似這樣:

var

contact = 上面的sql語句取出來的使用者所有的****;

foreach

(var

item in

contact)

}

當然你也可以嘗試下面這種寫法,我個人認為這種寫法更優雅

var

contact =上面的sql語句取出來的使用者所有的****;

txtworkphone.text

= (from

a in

contact

where

a.contactmethod ==contactmethod.work_phone

select

a.contactinfo).tostring();

//後面以此類推,***

select

contactinfo from

表 where

userrole=

某種使用者型別 and

ownerid=

某使用者id and

contactmethod=1//

取出某使用者的email

select

contactinfo from

表 where

userrole=

某種使用者型別 and

ownerid=

某使用者id and

contactmethod=8//

取出某使用者的homephone

相信我,這種做法非常愚蠢:每當你要取出這個使用者的一種****,就要和資料庫建立一次連線,開啟/關閉一次資料庫;這種做法代價是十分巨大的,即使有資料庫連線池,即使有資料庫快取,都應該避免這種愚蠢的做法

唔,用了那麼多的**,終於查出了某個使用者的聯絡資訊了。反正我個人覺得這種設計方式在查詢的時候,是邏輯上的浩劫。什麼?你說你很享受?好吧,看來是我腦容量不夠……

不過當我們面臨需求變動的時候,那就非常愉快了。

什麼,要加一類使用者?簡單,userrole加乙個列舉就好了。

什麼,要加一種****?contactmethod加乙個列舉就ok。

使用了這種表設計的時候,相信你會微笑著面對需求變動的

二逼青年

昨天和同事也**了下這個問題,按他的說法就是:哪個表要****,我就扔個字段進去,存json

contact

varchar(8000)

用於儲存json

舉例來說,有這麼乙個使用者:

id:1

name:張三

telphone:1234

email:[email protected]

fax:5678

那麼資料庫中就這樣存:

當我聽到這種設計思路的時候,虎軀微微一震:靠,這都行。按這種設計,我整張表都放進乙個json裡面一股腦的存進去就算了。不過震驚之後仔細想一想,其實這種設計也是有可取之處

首先,從查詢來說,和普通青年一樣,只需一句sql:

select

contact from

表 where

條件

查詢之後,就可以通過json處理函式將想要的資料取出來,在此就不贅述了

那麼當面臨需求變動的時候會發生什麼:

加一類使用者的時候,要新增一張表。也是符合開閉原則,原有**沒有改動

加一種****,只用存json的時候多存一點東西

不過這種設計如果要更新某條資料的話要稍微麻煩一點:先查詢一條資料,重組json之後再update

我們該如何設計資料庫

資料庫該如何設計,一直以來都是乙個仁者見仁智者見智的問題。對於某一種資料庫設計,並不能簡單的用好與不好來區分。或許真的應了那句話,沒有最好,只有最適合。討論某種資料庫設計的時候,應該在某種特定的需求環境下討論。下面來討論一下在專案中經常碰到的使用者的 儲存的問題。我在這裡套用之前網路上流行 普通 文...

我們該如何設計資料庫 三

簡單的說說吧 假設為man使用者實現的是乙個徵婚系統,而woman使用者實現的是乙個選美系統。這麼說應該能理解man和woman的不能並同一張表的原因了吧。在 我們該如何設計資料庫 二 中,園友jacklondon chen提出了一些問題,大致如下 man woman應該設計在同一張表中。使用者表大...

我們該如何設計資料庫 四

其實我一直在準備另一篇博文的基礎資料,但是和朋友聊天,他問我最近在做什麼,我說在做系統log模組,並和他交流了一下,於是這篇部落格就應運而生。其實我一直在準備另一篇博文的基礎資料,但是和朋友聊天,他問我最近在做什麼,我說在做系統log模組,並和他交流了一下,於是這篇部落格就應運而生。所有資料都可以用...