Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

資料庫架構設計實戰:補習班班務系統

最後更新:2026年1月13日資料庫

學完正規化和限制之後,我們來做一個實戰練習。

這次的任務是:幫一間補習班設計班務系統的資料庫。

這個系統要記錄什麼?

  • 有哪些課程(科目 + 年級)
  • 有哪些老師
  • 有哪些學生
  • 老師在什麼時間、什麼教室上什麼課
  • 學生選了哪些課

聽起來不難,但實際設計的時候,你會發現有很多細節要考慮。

讓我們一步步來。

找出有哪些個體

首先,我們要從需求中找出「有哪些東西」。

根據上面的描述,可以找出這些個體:

  • 老師:要記錄有哪些老師
  • 學生:要記錄有哪些學生
  • 課程:由科目和年級組成(例如:三年級數學)
  • 教室:老師在哪個教室上課

那「時間」呢?

時間比較特別。補習班的上課時間通常就是一個時間點,例如:「星期一 18:00」、「星期三 19:30」。

這些時間本身沒有什麼額外的性質需要記錄(不像教室有「容量」、老師有「姓名」),所以不一定需要另外切一張「時間表」,直接當作一個欄位就好。

那「科目」和「年級」呢?這要看情況,我們等一下再討論。

找出個體之間的關係

接下來,我們要想:這些個體之間有什麼關係?

什麼是講授

老師在特定的時間、特定的教室,教某一個課程。

這四個東西組合在一起,我們稱為「講授」。

例如:「David 老師在星期一 18:00,於 A101 教室,教三年級數學」就是一筆講授資料。

這是一個複雜的多對多關係:

  • 一個老師可以教很多課程
  • 一個課程可以被很多老師教(題目有特別強調這點)
  • 一個課程可以在很多教室上
  • 一個教室可以上很多課程(看時間安排)

課程、科目、年級的關係

課程是由科目和年級組成的。

例如:「三年級數學」這個課程 = 三年級 + 數學。

科目和年級也是多對多的關係:

  • 一個科目有很多年級(數學有一年級數學、二年級數學、三年級數學…)
  • 一個年級有很多科目(三年級有數學、英文、自然…)

學生選的是講授,不是課程

學生選課,選的是什麼?

直覺上你可能會覺得:學生選的是「課程」。

但仔細想想,如果這個課程還沒有老師教,學生怎麼選?

學生選的其實是「講授」——也就是「哪個老師教的哪個課程」。

例如:學生選的不是「三年級數學」,而是「David 老師的三年級數學班」。

決定要不要獨立成一張表

現在我們來決定每個個體要不要獨立成一張表。

科目和年級要不要獨立成一張表?

課程是由科目和年級組成的,例如「三年級數學」= 三年級 + 數學。

那我們需要另外建立「科目表」和「年級表」嗎?

在前一篇文章中,我們學到一個判斷原則:如果這個東西有「自己的性質」需要記錄,就應該獨立成一張表。

我們來檢查看看科目和年級有沒有額外的性質:

年級有什麼性質?

一年級、二年級、三年級… 好像就只有「幾年級」這個資訊,沒有其他要記錄的。

科目有什麼性質?

數學、英文、自然… 好像也只有「科目名稱」這個資訊,沒有其他要記錄的。

既然都沒有額外的性質,那就先不獨立成表,直接當作課程表裡的欄位就好:

課程 ID(PK)科目年級
1數學三年級
2英文三年級
科目數學
年級三年級
科目英文
年級三年級

什麼時候要獨立成一張表?

如果有一天,老闆說:「我想把科目分類,數學是理科、歷史是文科。」

這時候科目就有自己的性質(分類)需要記錄,就應該把科目獨立成一張表:

科目 ID(PK)科目名稱分類
1數學理科
2歷史文科
科目名稱數學
分類理科
科目名稱歷史
分類文科

結論:目前先不獨立成表,等有需要再說。

教室要不要獨立成一張表?

教室有沒有自己的性質?

有的:

  • 教室名稱(A101、A102…)
  • 教室容量(最多可以坐幾個學生)

既然教室有這些性質需要記錄,就應該獨立成一張表。

據點要不要獨立成一張表?

題目說目前只有一個據點(一間補習班)。

如果只有一個據點,不獨立成表也沒關係,因為所有資料都屬於這個據點。

但如果老闆說:「我們以後可能會開分校。」

那就應該把據點獨立成一張表。而且,其他表都要加上「據點 ID」欄位:

  • 老師屬於哪個據點?
  • 學生屬於哪個據點?
  • 教室屬於哪個據點?

這會增加設計的複雜度。所以如果要加這個彈性,記得跟老闆確認,也記得多收錢。

結論:看需求。目前只有一個據點,可以先不獨立成表。

設計表單結構

根據上面的討論,我們來設計表單。

人員表

老師和學生都是「人」,而且目前都只需要記錄姓名。

與其分成「老師表」和「學生表」,不如合併成一張「人員表」,用「身份」欄位區分。

人員 ID(PK)姓名身份
1David老師
2Emily老師
3Frank學生
4Grace學生
姓名David
身份老師
姓名Emily
身份老師
姓名Frank
身份學生
姓名Grace
身份學生

如果以後老師有額外的性質(例如:可以教的領域),再把老師表拆出來。

課程表

課程由科目和年級組成。

課程 ID(PK)科目年級
1數學三年級
2英文三年級
3數學二年級
科目數學
年級三年級
科目英文
年級三年級
科目數學
年級二年級

教室表

教室 ID(PK)名稱學生上限
1A10130
2A10225
3B20140
名稱A101
學生上限30
名稱A102
學生上限25
名稱B201
學生上限40

講授表

講授是老師、課程、教室、時間的組合。

講授 ID(PK)課程 ID(FK)講師 ID(FK)教室 ID(FK)時間
1111星期一 18:00
2122星期二 19:30
3211星期一 20:00
課程 ID(FK)1
講師 ID(FK)1
教室 ID(FK)1
時間星期一 18:00
課程 ID(FK)1
講師 ID(FK)2
教室 ID(FK)2
時間星期二 19:30
課程 ID(FK)2
講師 ID(FK)1
教室 ID(FK)1
時間星期一 20:00

注意:同一個課程(三年級數學)可以有不同老師教,所以課程 ID = 1 出現了兩次,分別是 David 和 Emily 教的。

講授表的三個 ID 欄位都是外部鍵(FK):

  • 課程 ID → 指向課程表的課程 ID
  • 講師 ID → 指向人員表的人員 ID
  • 教室 ID → 指向教室表的教室 ID

選課表

學生選的是「講授」,不是「課程」。

學生 ID(FK)講授 ID(FK)
31
33
42
講授 ID(FK)1
講授 ID(FK)3
講授 ID(FK)2

這張表的兩個欄位都是外部鍵:

  • 學生 ID → 指向人員表的人員 ID
  • 講授 ID → 指向講授表的講授 ID

這張表不需要額外的「選課 ID」嗎?

不一定需要。因為「學生 ID + 講授 ID」的組合本身就可以當作主鍵。

為什麼?因為同一個學生不會選同一個講授兩次。Frank(學生 ID = 3)選了 David 的三年級數學班(講授 ID = 1),他不可能再選一次。

所以「學生 ID = 3, 講授 ID = 1」這個組合在整張表裡只會出現一次,符合主鍵「不能重複」的條件。

這種用兩個欄位組合起來當主鍵的做法,叫做複合主鍵(Composite Primary Key)。

加上 PK、FK、NOT NULL 限制

現在我們來加上各種限制。

主鍵(PK)

所有的 ID 欄位都是主鍵:

  • 人員表:人員 ID
  • 課程表:課程 ID
  • 教室表:教室 ID
  • 講授表:講授 ID

NOT NULL

哪些欄位不能是空值?

  • 人員表:姓名、身份都不應該是 NULL
  • 課程表:科目、年級都不應該是 NULL
  • 教室表:名稱不應該是 NULL,學生上限看情況
  • 講授表:課程 ID、講師 ID、教室 ID、時間都不應該是 NULL
  • 選課表:學生 ID、講授 ID 都不應該是 NULL

外部鍵(FK)

表單欄位Reference(指向)
講授表課程 ID課程表.課程 ID
講授表講師 ID人員表.人員 ID
講授表教室 ID教室表.教室 ID
選課表學生 ID人員表.人員 ID
選課表講授 ID講授表.講授 ID
欄位課程 ID
Reference(指向)課程表.課程 ID
欄位講師 ID
Reference(指向)人員表.人員 ID
欄位教室 ID
Reference(指向)教室表.教室 ID
欄位學生 ID
Reference(指向)人員表.人員 ID
欄位講授 ID
Reference(指向)講授表.講授 ID

「課程表.課程 ID」是什麼意思?

這是一種表示「哪張表的哪個欄位」的寫法。

格式是:表單名稱.欄位名稱

例如:

  • 課程表.課程 ID = 課程表裡面的「課程 ID」欄位
  • 人員表.人員 ID = 人員表裡面的「人員 ID」欄位

所以「講授表的課程 ID 指向課程表.課程 ID」意思就是:講授表裡的「課程 ID」欄位,是一個外部鍵,它參考的對象是課程表裡的「課程 ID」欄位。

學生上限要放在哪裡?

這是一個有趣的問題。

學生上限可以放在很多地方:

  1. 放在教室表:按照教室容量決定(A101 最多 30 人)
  2. 放在課程表:按照課程決定(三年級數學最多 25 人)
  3. 放在講授表:按照講授決定(David 的三年級數學班最多 20 人)

哪個才對?

答案是:看你的業務邏輯。

  • 如果學生上限只跟教室有關 → 放在教室表
  • 如果學生上限跟課程有關 → 放在課程表
  • 如果學生上限跟「誰教」也有關(David 老師喜歡小班教學)→ 放在講授表
  • 如果以上都有關 → 可能每個表都要放,然後取最小值

這就是為什麼我們一直強調:沒有標準答案,要看情境。

加入據點表的設計

如果老闆說要開分校,我們就需要加入據點表。

據點表

據點 ID(PK)名稱
1總校
2信義分校
名稱總校
名稱信義分校

其他表要加上據點 ID

加入據點之後,老師、學生、教室都屬於某個據點。

人員表:

人員 ID(PK)姓名身份據點 ID(FK)
1David老師1
2Emily老師2
姓名David
身份老師
據點 ID(FK)1
姓名Emily
身份老師
據點 ID(FK)2

教室表:

教室 ID(PK)名稱學生上限據點 ID(FK)
1A101301
2A102252
名稱A101
學生上限30
據點 ID(FK)1
名稱A102
學生上限25
據點 ID(FK)2

課程要不要跟據點有關?不一定。如果所有分校教的課程都一樣,就不用關聯。如果有些分校只教特定課程(例如:自然組分校),那課程表也要加上據點 ID。

重點整理

這次的實戰練習,我們學到了幾件事:

設計資料庫的流程

  1. 找出個體:從需求中找出有哪些「東西」
  2. 找出關係:這些個體之間有什麼關係
  3. 決定拆表:根據正規化原則,決定要不要拆表
  4. 設計結構:設計每張表的欄位
  5. 加上限制:加上 PK、FK、NOT NULL 等限制

資料庫設計的核心觀念

  • 沒有標準答案:資料庫設計要看你的業務邏輯和情境
  • 彈性有成本:要保留彈性(例如:據點),就要多做設計,記得跟老闆多收錢
  • 先簡單再複雜:不確定的時候,先不拆表,等有需要再拆
  • 為業務邏輯服務:所有的設計都是為了讓業務邏輯更容易實現

設計資料庫的時候,記得把你的情境和考量寫清楚。這樣別人才能理解你為什麼這樣設計,也才能討論這樣設計合不合理。

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

資料庫

目錄

  • 找出有哪些個體
  • 找出個體之間的關係
  • 什麼是講授
  • 課程、科目、年級的關係
  • 學生選的是講授,不是課程
  • 決定要不要獨立成一張表
  • 科目和年級要不要獨立成一張表?
  • 教室要不要獨立成一張表?
  • 據點要不要獨立成一張表?
  • 設計表單結構
  • 人員表
  • 課程表
  • 教室表
  • 講授表
  • 選課表
  • 加上 PK、FK、NOT NULL 限制
  • 主鍵(PK)
  • NOT NULL
  • 外部鍵(FK)
  • 學生上限要放在哪裡?
  • 加入據點表的設計
  • 據點表
  • 其他表要加上據點 ID
  • 重點整理
  • 設計資料庫的流程
  • 資料庫設計的核心觀念