最後一節我們要來聊聊更深入關聯式資料庫觀念。今天我們先從討論 Entity-Relationship Model (ER Model,譯作 實體關係模型) 開始說起。
在第一節跟第二節的關聯式資料庫的討論中我們一直以來都著重在操作資料庫中的資料,但是如果今天你要為一個專案或者是一個平台創建一個資料庫這時候又該從何著手開始設計資料庫中的每一個元件呢?有時候當我們突然要面對一個不熟悉的關聯式資料庫,又或者是我們想要把關聯式資料庫中複雜的結構告訴別人,這時候有沒有什麼簡單易懂的圖表來協助我們傳的這些資訊?這就是為什麼會出現ER diagram (ERD) 的原因。
在這個小節中,我們會看到許多第二天第三天出現過的專有名詞。這邊我沒有辦法在有限的篇幅中,把所有可能出現的符號、或者是有比較複雜概念的符號全部一一解釋。在ERD的世界中,長方形的方格表示他是一個entity,也就是他是世界上的某一個實體。實體的諸多屬性我們就用長方形外面的橢圓形來表示這些屬性的名稱。接著我們使用菱形來表示兩個實體之間的關係,當然,這針對這一個關係,我們也可以賦予它不同的屬性。下面我放了一張 ERD 的範例,這張圖是存放一間醫院的資料所使用的ERD。(這邊省略的 Weak Entity 和 ISA 的概念沒有討論)
在這張圖的左邊,我們可以看到每一個病患具有一大堆的屬性 (例如: 姓名、性別、病患編號、地址、等等)。病患會被指派到房間,而且病患會被要求要支付診療和藥物的費用,同時我們也會看到病患要去看醫生,這些資訊就可以有這樣子的一張ERD的來做表示。
基數的意思就是,在解釋不同的實體之間,有沒有任何的限制。在關聯式的資料庫中,我們有四種可能的限制。第一種是一對一限制 (1-1),也就是一個左邊的實體僅會對應到一個右邊的實體,一個例子,就像是一個學生和考試成績。一份考卷由一個學生填答,反之亦然。第二種和第三種關係就比較容易理解 — 一對多關係或者是多對一關係 (1-N, N-1)。這邊可以舉的例子就像,一個國小的班級有很多的小朋友,但是每一個小朋友只會就讀一個班級。第四種關係就是多對多的關係 (N-N),可以想像的例子就像是一個學生有很多老師,每一個老師都會教很多的學生。
你可能會問說這些關聯重要嗎? 這些關聯會幫助我們決定如何在資料庫管理系統中配置資料。又或者是,那些數值應該視為主鍵(Primary Key)、那些又應該定義為外部鍵 (Foreign Key)。而且一般來說,當兩個實是多對多關係的時候,我們就必須要建立一個中繼的關聯表。延續剛剛上面的例子,一個學生有很多老師,每一個學生會教很多的學生,這時候我們就會有下面這樣的設計:
Student(sid, name)
Teacher(tid, name)
Teaches(tid, sid)
學生的關聯表存學生的資料,老師的關聯表存老師的資料,中間用一個關係表將兩個比串接起來。這樣的設計在資料庫管理系統維護上面更加地容易和簡潔。
這樣的基數限制一般來說我們會用小括號註記在實體旁邊。
但是因為上面這種表畫起來實在是有點混亂,所以資料庫中就有簡化過的ERD,讓我們來看看MySQL 中的ERD 長什麼樣子。我們來看看範例資料的ERD。
首先我們打開MySQL Workbench 選擇Reverse Engineering (或是按下 Ctrl/Cmd + R)
授權資料庫,完成後按下一步
選擇 World 範例資料按下一步然後下一步
選下一步然後案到底。
結果就會是這樣
這邊 Entity 一樣適用長方形表示,不同的是屬性資料都被放進這個長方形的框框中。物件實體的關聯用一條兩端有著奇怪符號線牽著
所以上面我們就可以說,一個或多個城市有一個獨一無二的國家,每一個國家有一種或多種語言。(虛線有其含義在這邊不多做解釋)
另外,在 MySQL Workbench 的ERD 介面甚至可以生成程式碼
複製的結果會如下
CREATE TABLE IF NOT EXISTS `world`.`city` (
`ID` INT NOT NULL AUTO_INCREMENT,
`Name` CHAR(35) NOT NULL DEFAULT '',
`CountryCode` CHAR(3) NOT NULL DEFAULT '',
`District` CHAR(20) NOT NULL DEFAULT '',
`Population` INT NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
INDEX `CountryCode` (`CountryCode` ASC) VISIBLE,
CONSTRAINT `city_ibfk_1`
FOREIGN KEY (`CountryCode`)
REFERENCES `world`.`country` (`Code`))
ENGINE = InnoDB
AUTO_INCREMENT = 4080
DEFAULT CHARACTER SET = latin1
明天和後天我們會討論兩個複雜但是極度重要的觀念: 功能支配關係 (Functional Dependencies) 和 資料庫正規化 (Normal Form)