1. 程式人生 > 其它 >04-資料庫表設計三正規化

04-資料庫表設計三正規化

1、表的設計正規化

設計正規化是設計表的依據,按照三正規化設計的表不會出現資料的冗餘

2、設計三正規化

--第一正規化:任何一張表都應該有主鍵,並且每一個欄位原子性不可再分
	不可再分表示該欄位不應該可以自分一張表,例如學生和班級,如果放進一張表,班級這個欄位還是可以再分成班級表,該表中有班級編號和班級名字,所以這些個欄位不能放在一張表中,每個欄位是原子性
	一個表不能沒有主鍵。
	
--第二正規化:是在第一正規化的基礎上,所有非主鍵欄位完全依賴一個主鍵欄位,不能有部分依賴
例子:一張表中有學生編號sno,學生名sname,教師編號tno,教師名tname,該表中將欄位sno和tno聯合起來做一個複合主鍵,此時就有sname依賴sno,又有tname依賴tno,這時資料就冗餘了
這種該怎麼設計呢?
	因為每一個學生有多名教師,每位教師又有多位學生,是多對多的關係
--所以多對多,三張表,其中關係表有兩個外來鍵約束

學生表
sno(pk)		sname
------------------
1			張三
2			李四
3			王五

教師表
tno(pk)		tname
----------------------
1			李老師
2			王老師
3			陳老師

教師與學生的關係表
id(pk)		sno(fk)		tno(fk)
---------------------------------------
1			1			2
2			1			3
3			2			1
4			2			2
5			2			3
....
--第三正規化:在第二正規化的基礎上,所有非主鍵欄位依賴主鍵,不能產生傳遞依賴
例如,學生和班級,一張表中,學號、姓名、班號、班名,此時僅將學號定為主鍵,此時班號依賴學號主鍵,但是班名卻依賴班號,然而班號卻不是主鍵,這是不行的。
一個班級有多名學生,這是一對多的關係
--所以這樣設計,一對多,兩張表,多的表加外來鍵

班級t_class表
cno(pk)		cname
--------------------
1			banji1
2			banji2

學生表t_student
sno(pk)		sname		cno(fk)
---------------------------------
1			zz			1
2			ss			2
3			ww			1
4			ee			2
--實際開發中,以客戶需求為準,有時候會拿冗餘換執行速度	

3、一對一怎麼設計?

一張使用者表t_user一般有使用者名稱和密碼,當然還有其他資訊,此時我們將這張大表拆分成兩張表:
	使用者登入表t_ulogin:其中儲存使用者名稱和密碼
	使用者詳細資訊表t_udetail:儲存有使用者名稱,住址等其他資訊
這時有兩種設計方案:
--主鍵共享
將t_udetail表的主鍵用t_ulogin表的主鍵約束
t_ulogin表
id(pk)		uname	password
------------------------------
1			zz		123
2			xx		123
t_udetail表
id(pk+fk)	realname	adress		phonenum
-----------------------------------------
1			雜雜		xcccv		123365
2			學習		csdsd		462616

--外來鍵唯一
t_udetail表中的一個userid欄位用t_ulogin表的主鍵,並且該欄位unique約束
t_ulogin表
id(pk)		uname	password
------------------------------
1			zz		123
2			xx		123
t_udetail表
id(pk)	realname	adress		phonenum		userid(fk+unique)
-------------------------------------------------------------------
1			雜雜		xcccv		123365			1
2			學習		csdsd		462616			2
--一對多的變形,多的表中外來鍵加了unique約束
資料表的幾種的關係
  • 一對一:學生和學生證
  • 一對多:學生和班級
  • 多對多:學生和課程
如何表示資料庫表之間的關係
  • 使用外來鍵:資料庫外來鍵關係表示的其實是一種一對多的關係
  • 一對一:外來鍵+唯一
  • 多對多:引入中間表,把一個多對多表示為兩個一對多

4、表設計的三大正規化

所謂正規化,即如何建立科學的,規範的的資料庫,需要滿足一些規範的來優化資料資料儲存方式的指導辦法。

第一正規化(1NF)
  • 每一列屬性都是不可再分的屬性值,確保每一列的原子性
  • 合理的根據實際業務資料需求來決定屬性,合併相似或相同的列,避免冗餘

假如有一個業務需求是:需要了解一批使用者的基礎資訊(包括姓名,年齡,電話,詳細地址,以及根據地址明細進行分類),如果資料庫表設計如下,則不滿足第一正規化:

不滿足第一正規化示例

以上例項中設計了地址,如果需求根據進行分類則無法實現
【解決辦法】根據需求適當的將地址拆分為更原子的省市兩個屬性即可符合第一正規化

第二正規化(2NF)
  • 需要確保資料庫表中的每一列都和主鍵相關,如果是聯合主鍵,則需要和所有主鍵均相關而不能只與主鍵和某一部分相關
  • 在一個數據庫表中只能儲存一種資料,不可以把多種資料儲存在同一張資料庫表中

假設有表如下,學號和課程編號是聯合主鍵,但是,該表中,課程名稱和學號沒有任何關係,學生姓名和課程編號也沒有任何關係

不滿足第二正規化示例

【解決辦法】(1)提取學生表;(2)提取課程表;(3)建立學生課程關係表。
值得注意的是,學生表只儲存學生的基本資訊屬性;課程表只儲存課程的相關屬性;學生課程關係表,只儲存學號(學生表主鍵)和課程編號(課程表主鍵)以及一些其他學生課程關係的屬性欄位,並不儲存學生基本資訊和課程相關資訊,即可符合第二正規化

第三正規化(3NF)
  • 確保資料表一個記錄中的資料都和主鍵直接相關,而不是間接相關,不能存在傳遞關係
  • 屬性不依賴於其他非主屬性

假設有如下表,學號為主鍵,它存在 學號 --> 班級編號 --> 班級資訊 這麼一個主鍵學號與班級資訊的傳遞關係,不符合第三正規化

不符合第三正規化示例

【解決辦法】(1)提取學生表;(2)提取班級表;
學生肯定在某一個班級中,所以班級編號可以作為學號(主鍵)的一個直接關聯屬性,但班級的其他資訊應該放在以班級編號為主鍵的表中,即可符合第三正規化。

遵循正規化的優缺點

通過以上的瞭解,可以發現,正規化規則有如下特點

  • 結構合理,表含義容易理解及區分
  • 冗餘較小
  • 但效能有所降低,多表查詢比單表效率低下
五大約束:

資料庫中的五大約束包括:

1.主鍵約束(Primay Key Coustraint) 唯一性,非空性;

2.唯一約束 (Unique Counstraint)唯一性,可以空,但只能有一個;

3.預設約束 (Default Counstraint) 該資料的預設值;

4.外來鍵約束 (Foreign Key Counstraint) 需要建立兩表間的關係;

5.非空約束(Not Null Counstraint):設定非空約束,該欄位不能為空。

五大約束的語法示例:

\1. 新增主鍵約束

Alter table 表名 add Constraint 主鍵名 primary key(欄位)

\2. 新增唯一約束

Alter table 表名 add Constraint 約束名 unique(欄位)

\3. 新增預設約束

Alter table 表名 add Constraint 約束名 default(預設內容) for 欄位名

\4. 新增檢查約束

Alter table 表名 add Constraint 約束名 check (欄位表達)

\5. 新增外來鍵約束

Alter table 表名 add Constraint 約束名 foreign key(欄位) references 表名(欄位名)

詳細介紹:

(1)[外來鍵約束 (Foreign Key Counstraint) ]
1.設定外來鍵的注意事項:

  ①:只有INNODB的資料庫引擎支援外來鍵,修改my.ini檔案設定default-storage-engine=INNODB;
  ②:外來鍵與參照列的資料型別必須相同。(數值型要求長度和無符號都相同,字串要求型別相同,長度可以不同);
  ③:設定外來鍵的欄位必須要有索引,如果沒有索引,設定外來鍵時會自動生成一個索引;

2.設定外來鍵的語法:

[CONSTRAINT 外來鍵名] FOREIGN KEY(外來鍵欄位) REFERENCES 參照表(參照欄位) [ON DELETE SET NULL ON UPDATE CASCADE] -- 設定操作完整。

3、外來鍵約束的參照操作:

當對參照表的參照欄位進行刪除或更新時,外來鍵表中的外來鍵如何應對。
參照操作可選值:
  RESTRICT: 拒絕對參照欄位的刪除或修改(預設);
  NO ACTION:與RESTRICT相同,但這個指令只在MySql生效;
  CASCADE: 刪除或更新參照表的參照欄位時,外來鍵表的記錄同步刪除或更新;
  SET NULL: 刪除刪除或更新參照表的參照欄位時,外來鍵表的外來鍵設為NULL (此時外來鍵不能設定為NOT NULL)。

(2)[主鍵約束](Primay Key Coustraint)

1.主鍵的注意事項:主鍵預設非空,預設唯一性約束,只有主鍵可以設定自動增長(主鍵不一定自增,自增一定是主鍵)。
2.設定主鍵的方式:

  ①:在定義列時設定:id INT UNSIGNED PRIMARY KEY。
  ②:在列定義完成後設定:PRIMARY KEY(id)。