#### 1. 什么是設(shè)計范式 ---- 設(shè)計表的依據(jù),按照范式設(shè)計出來的表,不會出現(xiàn)數(shù)據(jù)的冗余 數(shù)據(jù)庫的設(shè)計范式是數(shù)據(jù)庫設(shè)計所需要滿足的規(guī)范,滿足這些規(guī)范的數(shù)據(jù)庫是簡潔的、結(jié)構(gòu)清晰的;反之則是亂七八糟,不僅會給開發(fā)人員制造麻煩,而且還可能存儲了大量不需要的冗余數(shù)據(jù) 不僅僅只有三大范式,還有第四范式、第五范式、第六范式等,通常來講,滿足三大范式就基本足夠 項目的數(shù)據(jù)庫設(shè)計并不一定要完全滿足于三大范式,有些時候我們會適量的冗余讓 query 盡量減少 join #### 2. 三大范式 ---- **第一范式(1 NF):要求屬性(列)具有原子性,即每列都是不可再分解的數(shù)據(jù)** 雖然第一范式要求各列保存原子性,不能再分解,但是這種要求是和我們的需求相關(guān)聯(lián)的,不拆分也行;如果要考慮可擴展性,那么就進行拆分吧。如下表所示,沒有根據(jù)城市篩選用戶的需求,可以這樣存儲城市數(shù)據(jù) | id | name | address | | ------------ | ------------ | ------------ | | 1 | 張三 | 河南省開封市蘭考縣 | | 2 | 李四 | 廣東省深圳市福田區(qū) | 對 address 進行拆分,使其具有原子性(原子性:指不可再分解的意思) | id | name | province | city | area | | ------------ | ------------ | ------------ | ------------ | ------------ | | 1 | 張三 | 河南省 | 開封市 | 蘭考縣 | | 2 | 李四 | 廣東省 | 深圳市 | 福田區(qū) | **第二范式(2 NF):建立在第一范式基礎(chǔ)上,除主鍵外的每一列都必須完全依賴于主鍵** 如果要出現(xiàn)不完全依賴主鍵,只可能發(fā)生在聯(lián)合主鍵的情況下 第二范式是對記錄的唯一性約束,要求有唯一性標識,即實體的唯一性,如下所示:即可 name 和 address 完全一致,但是主鍵值是不一樣的,這樣就實現(xiàn)了數(shù)據(jù)的唯一性 | id | name | address | | ------------ | ------------ | ------------ | | 1 | 張三 | 河南省開封市蘭考縣 | | 2 | 張三 | 河南省開封市蘭考縣 | **第三范式(3 NF):建立在第二范式基礎(chǔ)上,對字段冗余性的約束,它要求字段沒有冗余** 假設(shè)員工的薪資水平由崗位決定,也就是 salary 由 job 決定,和人員(name)無關(guān) 員工表: | id | name | job | salary | | ------------ | ------------ | ------------ | ------------ | | 1 | 張三 | Web 前端開發(fā)工程師 | 5000 | | 2 | 李四 | PHP 后端開發(fā)工程師 | 8000 | | 3 | 王五 | PHP 后端開發(fā)工程師 | 8000 | 那么,我們將遵循第三范式將員工表拆分為兩張表,如下所示 員工表: | id | name | job_id | | ------------ | ------------ | ------------ | | 1 | 張三 | 100 | | 2 | 李四 | 101 | | 3 | 王五 | 101 | 薪資表: | id | name | salary | | ------------ | ------------ | ------------ | | 100 | Web 前端開發(fā)工程師 | 5000 | | 101 | 后端開發(fā)工程師 | 8000 |