若要打造像 Udemy 這樣的高效線上課程平台,正確的資料庫設計就是成長與穩定的關鍵。透過清晰的實體關係、結構化的表以及可擴展的架構,你不僅能同時支援成千上萬的課程與學生互動,還能確保課程、模組、測驗等內容以高效的方式載入與維護,為未來新增功能留出成長空間。
在實務設計中,我會把課程與學生的關係拆解成多個核心表,並以加入表連結,讓查詢更快、維護更清晰。例如為了支援「必須完成前一課才能進入下一課」的學習路徑,我們引入 is_progress_limited 與 course_order 的分離,讓前端邏輯與資料層可以獨立演繹;測驗、答案與分數等資料也各自獨立成表,便於追蹤與優化。這些決策源自對學習路徑與商業需求的深入觀察,確保平台在擴充課程與功能時,仍能維持出色的效能與穩定性。
文章目錄
- 打造精準的課程資料模型 包含 課程 模組 課程單元 與 測驗 的結構與關係
- 多對多關係與加入表的實務要點 包含 Enrolment 與 student_quiz_attempt 的設計 外鍵 與 索引策略
- 課程進度與評分機制最佳實務 包含 course_order is_progress_limited min_pass_score 完成日期時間 與 完成狀態 的設計
- 媒體資源與支付資料的安全與效能處理 避免 在 資料庫 存放 影音檔案 使用 參考連結 與 外部支付整合
- 性能與自動化落地策略 基於 ERD 驅動 開發 產出 SQL 腳本 正規化 擴充性 指標 與 監控
- 常見問答
- 總的來說
打造精準的課程資料模型 包含 課程 模組 課程單元 與 測驗 的結構與關係
在打造精準的資料模型時,我以 Udemy 的案例為藍本,將核心實體鎖定為課程(Course)、模組(Module)、課程單元(Lesson)與 測驗(Quiz),並以它們之間的結構與關係作為設計核心。這樣的模型能清晰反映課程內容的層級、學習路徑,以及學員與課程之間的多對多關係,並支援追蹤學習進度與評量結果。
- 多對多關係:我採用 join table Enrolment 連結 課程與 學員,以保留學員在不同課程中的註冊紀錄與進度。
- 主鍵與外鍵:每個實體都具備 ID 作為主鍵; joining 表需要正確的外鍵參照。
- 階層關係:模組 (Module) 屬於課程,課程單元 (Lesson) 屬於模組,皆新增外鍵與排序欄位以支援前端導覽。
- 支付資訊處理:不在資料庫中存放支付明細;支付可由 Stripe/Paypal 完成,於資料表僅紀錄是否付費、付費時間等最小資訊。
- 課程排序與學習限制:新增
course_order、is_progress_limited,讓課程可以控制學習順序與是否必須按部就班完成。 - 測驗結構:測驗 (Quiz) 可附屬於課程任意時點,另建
quiz_question、quiz_answer等表以儲存題目與答案,並支援多個正確答案。 - 成績與紀錄:建立
student_quiz_attempt以記錄學生的嘗試時間與分數,便於回顧與驗證。 - 進度追蹤:為課程單元完成狀態建立
student_lesson,並使用 completed_datetime或布林欄位記錄完成時間。 - 完成時間:在
enrolment表中加入completed_datetime,以捕捉整個課程的完成時間點。
| 資料表 | 核心欄位 / 外鍵 | 說明 |
|---|---|---|
| course | course_id (PK), name, description, price | 課程主資料與定價欄位 |
| student | student_id (PK), Email, password | 學員基本資訊 |
| enrolment | enrolment_id (PK), course_id (FK), student_id (FK), enrolment_datetime, completed_datetime | 學員與課程的註冊與完成時間紀錄 |
| module | module_id (PK), course_id (FK), name, module_number | 課程模組與隸屬課程 |
| lesson | lesson_id (PK), module_id (FK), name, lesson_number, course_order | 課程單元與排序 |
| quiz | quiz_id (PK), course_id (FK), name, course_order, min_pass_score, is_pass_required | 測驗及其在課程中的排序與通過規則 |
| quiz_question | quiz_question_id (PK), quiz_id (FK), title | 測驗題目 |
| quiz_answer | quiz_answer_id (PK), quiz_question_id (FK), text, is_correct | 題目選項與正確性 |
| student_quiz_attempt | attempt_id (PK), quiz_id (FK), student_id (FK), attempt_datetime, score | 學生測驗嘗試紀錄 |
| student_lesson | record_id (PK), student_id (FK), lesson_id (FK), completed_datetime | 單元完成紀錄 |
透過這樣的設計與實作要點,你的線上課程平台能更容易擴充、追蹤學習進度,並確保測驗與完成度的數據一致性。如果你想取得完整的 ER 圖與建立表格的 SQL 腳本,請參考我為此專案整理的 PDF,內含最終 ER 圖、欄位說明以及建立表格的 SQL。你可以到 databasestar.com/dbdesign 找到連結。
多對多關係與加入表的實務要點 包含 Enrolment 與 student_quiz_attempt 的設計 外鍵 與 索引策略
核心結論是:在多對多關係設計中,應以加入表作為核心,透過外鍵連結主實體,並於常見查詢路徑加上合適的索引,才能支撐高併發與快速回應。以下以 Enrolment 與 student_quiz_attempt 為例,說明實務要點、外鍵設計與索引策略。
• 多對多關係核心:以加入表連結課程與學生,避免在原始表中放置重複且難以維護的欄位。
• 兩個典型加入表的定位:Enrolment 用於「學生註冊課程」的關係;student_quiz_attempt 用於「學生對測驗的每次作答與分數」的紀錄。
• 一開始就規劃好外鍵與索引,確保利於常見查詢與資料完整性。
Enrolment(註冊)表的設計要點如下:
• 欄位核心:id(PK)、student_id(FK)、course_id(FK)、enrolment_datetime、completed_datetime。
• 唯一性與完整性:UNIQUE KEY (student_id, course_id) 以避免同一學生重複註冊同一課程;外鍵需設置參照完整性。
• 外鍵約束範例:FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE;FOREIGN KEY (course_id) REFERENCES course(id) ON DELETE CASCADE。
• 索引策略:建立複合索引 (student_id, course_id) 與 (course_id, student_id),另針對 enrolment_datetime 建立索引以加速以日期範圍查詢的新註冊或趨勢分析。
• 設計要點補充:可把 completed_datetime 設為 NULL 表示尚未完成,完成時間再更新,方便計算完成進度與完成時間分布。
student_quiz_attempt(學生測驗作答紀錄)表的設計要點如下:
• 欄位核心:id(PK)、student_id(FK)、quiz_id(FK)、attempt_datetime、score、以及必要的評分欄位(如 max_score)等。
• 外鍵與關聯性:FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE;FOREIGN KEY (quiz_id) REFERENCES quiz(id) ON DELETE CASCADE,確保學習紀錄的完整性與清理。
• 多次作答彈性:允許同一學生對同一測驗多次作答,因此避免在 (student_id, quiz_id) 上設定唯一鍵;若要追蹤「第幾次作答」,可再加入 attempt_no 欄位。
• 索引策略:建立索引 (student_id, quiz_id) 以快速取得某學生對某測驗的所有作答;再建立 (quiz_id, student_id) 以支援以測驗為單位的分析;另 (attempt_datetime) 可用於時間序列分析與趨勢報告。
• 資料型別建議:score 使用 DECIMAL(5,2) 或 FLOAT,依驗證需求與數值穩定性選擇。
| 表名 | 核心欄位 | 外鍵參照 | 推薦索引 | 設計要點 |
|---|---|---|---|---|
| Enrolment | id, student_id, course_id, enrolment_datetime, completed_datetime | student_id → student(id); course_id → course(id) | (student_id, course_id), (course_id, student_id), (enrolment_datetime) | 唯一性: UNIQUE (student_id, course_id); ON DELETE CASCADE 避免孤兒記錄 |
| student_quiz_attempt | id, student_id, quiz_id, attempt_datetime, score | student_id → student(id); quiz_id → quiz(id) | (student_id, quiz_id), (quiz_id, student_id), (attempt_datetime) | 允許多次作答;如需追蹤第幾次,考慮加入 attempt_no |
課程進度與評分機制最佳實務 包含 course_order is_progress_limited min_pass_score 完成日期時間 與 完成狀態 的設計
打造高效線上課程平台的終極數據庫設計,重點聚焦於你提到的「course_order、is_progress_limited、min_pass_score、完成日期時間 與 完成狀態」的設計要點。根據 Udemy 類似的設計流程,你將建立多對多的課程與學生關係,透過 enrolment 作為連接表連結 course 與 student,同時以模組、章節與測驗的層級架構,藉由 course_order 控制課程大綱的顯示順序,讓使用者體驗不受單一編號限制,並以後端邏輯掌控進度與完成狀態。
在欄位設計與表結構上,建議採取以下做法:
- enrolment 作為課程與學生的 join 表,含有
student_id、course_id、enrolment_datetime,以及完成整個課程的時間可透過completed_datetime追蹤。 - 為了顯示順序的彈性,將 course_order 欄位同時加入 lesson 與 quiz,定義其在課程大綱中的順序,透過修改此欄位即可調整排序而不改動原有編號。
- is_progress_limited 作為布林欄位,若為 True,表示必須完成前一課才能開啟下一課的進度限制。
- 在 quiz 表中新增 min_pass_score,定義學生必須達到的最低分數;並設置 is_pass_required 作為是否必須及格才能繼續的旗標。
- 建立 student_quiz_attempt,記錄學生對測驗的每次嘗試:
attempt_datetime、score,以便自動驗證分數是否符合最低通過分數。 - 為每個課程單元建立 student_lesson,紀錄完成狀態:使用
completed_datetime或布林is_completed,推薦以完成事件的日期時間來推斷完成狀態,提供更豐富的分析能力。
實作上你會發現,這樣的設計與 Udemy 的示例高度契合:付款細節不放在課程資料庫的核心表中,而是交給獨立的支付服務處理;同時,資料庫透過完成時間點 (completed_datetime) 與完成狀態旗標 (is_completed) 提供精準的進度分析與進度控管。為提升效能與可維護性,建議在外鍵與常用查詢欄位上建立適當的索引,並採用 UTC 儲存時間,以利跨區域的一致性與分析追蹤。
| 欄位 | 用途 | 建議資料型別 | 備註 |
|---|---|---|---|
| course_order | 課程大綱顯示順序 | INT | 可在 lesson 與 quiz 之間自由排序,與名稱分離以提升可維護性 |
| is_progress_limited | 是否必須完成前一課才能開啟下一課 | BOOLEAN/TINYINT | 預設 False;True 即啟用限制 |
| min_pass_score | 測驗最低通過分數 | DECIMAL(5,2) 或 FLOAT | 用於自動評分判斷 |
| completed_datetime | 完成事件的日期與時間 | DATETIME | 用於推斷完成與時間線分析 |
| is_completed | 完成狀態旗標 | BOOLEAN | 快速查詢;建議以 completed_datetime 為主、此欄作輔助 |
媒體資源與支付資料的安全與效能處理 避免 在 資料庫 存放 影音檔案 使用 參考連結 與 外部支付整合
直接要點:在設計高效的影音內容呈現時,請務必把影音檔案與媒體相關資訊與存取機制分離出來。避免在資料庫直接存放影音檔案,改以「媒體資源表」儲存元資料與「參考連結」指向外部儲存或流媒體服務,並透過 CDN 提供快取與簽名 URL 控制存取。這樣可顯著降低資料庫尺寸、提升查詢效能,並讓外部服務承載大檔案的壓力。以下是具體欄位設計與關聯的落地實作:
| 欄位 | 說明 |
|---|---|
| media_id | 媒體主鍵 |
| course_id / lesson_id / module_id | 關聯到內容單元 |
| media_type | video/audio/document |
| url | 外部儲存的原始連結或簽名連結 |
| provider | 外部提供商名稱(如 S3、CloudFront、Vimeo) |
| mime_type | 檔案類型 |
| size_bytes | 檔案大小 |
| duration | 長度(如適用) |
| signed_url_expiry | 簽名連結到期時間 |
當前的設計原則是:在課程單元(lesson)層級儲存「媒體參考」而非實際檔案,並以外部儲存與流媒體服務負責內容分發;同時利用簽名連結與 CDN 目標取代本地可直接存取的檔案路徑,確保安全與效率並行。
支付資料的安全整合:不要在本系統中儲存信用卡號或完整支付資訊;改以外部支付提供商完成交易,如 Stripe、PayPal 等,僅在本系統內存放交易紀錄與元資料。建議欄位有:交易 ID、使用者、課程、金額與貨幣、狀態、建立與更新時間、以及外部提供商的交易識別碼。亦應設定網路钩子(webhook)驗證、最小化資料留存,並遵循 PCI-DSS 原則,使用票證化或代替性金流資料。以下為支付相關欄位與關聯的範例表格:
| 欄位 | 說明 |
|---|---|
| transaction_id | 本系統交易主鍵 |
| user_id | 使用者ID |
| course_id | 相關課程ID |
| provider | 支付提供商(如 Stripe、PayPal) |
| provider_txn_id | 外部提供商的原始交易識別碼 |
| amount | 支付金額 |
| currency | 幣別 |
| status | 交易狀態(如 succeeded、failed、refunded) |
| created_at | 建立時間 |
| updated_at | 最近更新時間 |
| is_refunded | 是否已退款 |
透過上述設計,你可以在不暴露敏感支付資訊的前提下,完整追蹤每筆交易與課程取得狀態,並利用外部支付商的 webhook 進行自動化驗證與對帳。
效能與安全的實作要點:
- 媒體存取安全:使用簽名 URL、到期時間與白名單,避免未經授權的直接存取;結合 CDN 設定與「先驗證再載入」的存取流程。
- 內容分發與快取:部署 CDN、分段載入策略、使用 Cache-Control、ETag 等快取機制,降低重複流量與延遲。
- 日誌與審計:建立 media_access_log、payment_audit 的事件日誌,方便追蹤使用者存取與交易歷史。
- 非同步處理:將影音轉碼、上傳與鏈接生成等耗時任務改為非同步任務,提高上線穩定性。
- 最小化資料留存與分離:媒體與支付資料分表管理,避免將大檔案與高頻查詢混在同一張表;定期清理過期簽名與不再需要的參考連結。
| 領域 | 實務要點 |
|---|---|
| 媒體資源與參考連結 | 外部儲存與簽名連結、CDN、授權控管 |
| 支付資料 | 只存交易紀錄與外部交易識別碼、Webhook 驗證、PCI-DSS 合規與票證化 |
| 效能與日誌 | 索引、分表、緩存策略、事件日誌與監控 |
性能與自動化落地策略 基於 ERD 驅動 開發 產出 SQL 腳本 正規化 擴充性 指標 與 監控
本節聚焦在以 ERD 驅動的開發流程,落地 性能與自動化。透過模仿 Udemy 等在線課程平台的實戰案例,說明如何把需求轉化為可執行的 SQL 腳本,並建立以 正規化 與 擴充性 為核心的指標與監控機制,確保系統在用戶量成長時仍然穩定。你將 learn 如何把「需求-實體-關係」逐步轉為可維護的資料庫設計,並以實作細節支撐性能提升與自動化落地。
核心要點如下:
– ERD 驅動的開發流程:以實體與關係為中心,確保需求可被具體化為表與欄位,並以外鍵維護資料一致性。
– 主要實體與多對多關係:course 與 student 透過 joining 表 enrolment 建立多對多關係,並記錄 enroll 的時間與完成狀態。
– 欄位設計與正規化:course、student、enrolment、module、lesson、quiz、quiz_question、quiz_answer 等表,各自具備主鍵與外鍵,以及像 enrolment_datetime、course_order、completed_datetime 等欄位以支持後續擴充。
– 模組與課程內容分層:為課程設置 module 與 lesson,lesson 具備 video_url 與 lesson_details,避免直接在資料庫存放影音檔案,仍能完整呈現課程內容。
– 測驗與進度控制:quiz 與其題目與答案結構,新增 min_pass_score、is_pass_required,以及 course_order 與 lesson 的分離欄位,支援靈活的課程結構與顯示順序。
– 進度與完成度追蹤:透過 student_lesson、student_quiz_attempt、enrolment 的 completed_datetime 等欄位記錄,提供完成比例與可追溯的時間戳記,便於分析與自動化決策。
– 自動化產出與監控:以版本化 SQL 腳本產出、逐步遷移與回滾策略為核心,並建立可觀測的監控指標,確保擴充時仍具穩健性與可追溯性。
下方提供精煉的關鍵表格與欄位要點,協助你快速落地實作:
| 表名 | 用途/欄位要點 |
|---|---|
| course | ID, 名稱, 說明, 價格, is_progress_limited |
| enrolment | student_id, course_id, enrolment_datetime, completed_datetime |
| module | id, course_id, name, number |
| lesson | id, module_id, name, number, video_url, lesson_details, course_order |
| quiz | id, course_id, name, number, min_pass_score, is_pass_required, course_order |
| quiz_question | id, quiz_id, title |
| quiz_answer | id, question_id, text, is_correct |
| student_lesson | student_id, lesson_id, completed_datetime |
| student_quiz_attempt | student_id, quiz_id, attempt_datetime, score |
在指標與監控方面,建議聚焦以下核心要點:完成率、平均完成時間、各階段的通過率、查詢與回報的響應時間,以及以完成事件的時間戳記為基礎的可觀測性。為了實現穩健的自動化落地,採用版本控管的 SQL 腳本、遷移與回滾策略,並以自動化測試與定期監控報告確保長期可維護與快速迭代。透過這樣的設計與流程,你能在提升網站性能的同時,為未來的內容豐富與使用者規模成長打下穩固基礎。
常見問答
🧩 如何在資料庫中實作線上課程與學生的多對多關係?
直接答案是:使用 enrolment 作為 join table 來實作學生與課程的多對多關係。課程與學生各自有主鍵 ID,enrolment 需要外鍵連結兩端;未來也可在 enrolment 增加欄位如 enrolment_datetime 以紀錄註冊時間。這樣的設計滿足核心需求,並為後續模組、課程與測驗等關聯提供穩固基礎。
📚 如何讓課程內容遵循順序並追蹤完成狀態?
直接答案是:透過在課程結構中使用 course_order 與 is_progress_limited 來控制順序與進度。課程中的課程單元(如課程、測驗)分別新增 course_order,以確保顯示順序;同時在課程層級設置 is_progress_limited,決定是否必須依序完成才能前往下一步。此外,使用 student_lesson 的完成紀錄與 completed_datetime 來追蹤每位學生的完成情況,提供可追蹤的完成時間與進度。
✅ 如何設計測驗與成績的資料結構以支援多次測驗與通過條件?
直接答案是:透過 quiz、quiz_question、quiz_answer、student_quiz_attempt 等表,以及 min_pass_score 與 is_pass_required 欄位,支援多次測驗與通過條件。測驗可屬於課程,且每題有對應的 quiz_question 與多個 quiz_answer(is_correct 標示正確答案);學生可透過 student_quiz_attempt 記錄每次測驗的日期、分數與關聯外鍵。min_pass_score 定義及格門檻,is_pass_required 讓系統在必要時要求通過才能繼續。如此設計能清楚追蹤測驗分數、題型與多次嘗試情況。
總的來說
在本文的結尾,讓我們把本影片所揭示的線上課程平台資料庫設計要點整理成清晰的要點,幫助你快速掌握建立高效系統的關鍵資訊增益。
關鍵洞見與資訊增益
– 採用 enrolment 作為 course 與 student 的多對多關係連接表,清楚記錄註冊與時間。穩健的結構讓後續分析與查詢更具彈性。
– 每個實體都以主鍵(PK)與外鍵(FK)為核心,確保資料一致性與可追溯性,並支援日後的擴充與維護。
– student 表包含 Email 與 password 等認證資訊,為使用者管理與登入提供穩固基礎。
– course 表設計為名稱、描述與價格等屬性,建議同時標註貨幣以避免混淆。
– 支付細節不直接存放於系統資料庫,留給 Stripe、Paypal 等第三方支付服務處理,提升安全性與合規性。
– modules 與 lessons 的設計以層級關聯為核心:module 屬於課程、lesson 屬於模組,透過外鍵建立清晰的階層結構。
– Lesson 的影片僅以 URL 或引用物件的方式存取,避免直接在資料庫中儲存實際影片檔案,節省存儲並提升效能。
– lesson_details 用於存放課程文字說明與資源連結,資訊可用於豐富課程內容。
– is_progress_limited 作為布林值,決定學生是否必須按順序完成課程中的每一個 lesson,以控制學習流程。
– quiz 的設計採用單獨的表,並配合 quiz_question 與 quiz_answer,且各題都可標示正確答案(is_correct),同時提供多個正解的情況。
– 為避免顯示順序與實際課程結構脫節,新增 course_order 於 lesson 與 quiz,讓題目與單元的展示順序更具彈性與可控性。
– min_pass_score 為測驗的最低及格分數,並用 student_quiz_attempt 記錄學生的每次作答與分數,以利成績驗證與進度控管。
– is_pass_required 設為布林值,以決定是否必須通過該測驗才能繼續下一步,與課程層級的進度限制互相配合。
– 對於學習完成狀態,使用 student_lesson 來記錄每次是否完成與完成時間(completed_datetime),相較布林值更富有時效性與可分析性。
– 最後以 enrolment 表的 completed_datetime 來追蹤整個課程的完成狀態,全程資料的時間戳記提供更精確的學習歷程分析。
立即行動
📝 Get the design adn SQL for this database (and more): https://databasestar.mykajabi.com/lpkj-dbdesign/?video=FZVHZTaot1E
🎓 Turn yoru idea into a real database: https://databasestar.mykajabi.com/edd/?video=FZVHZTaot1E
An online course website,such as Udemy or Pluralsight,will let students enrol in courses,complete lessons within the courses,and take quizzes.
In this video, you’ll see how to design a database for an online learning management or online course system. We’ll go through a range of requirements one by one, and create a database design (Entity Relationship Diagram) from scratch, getting to a diagram that meets all of the requirements.

中央大學數學碩士,董老師從2011年開始網路創業,教導網路行銷,並從2023年起專注AI領域,特別是AI輔助創作。本網站所刊載之文章內容由人工智慧(AI)技術自動生成,僅供參考與學習用途。雖我們盡力審核資訊正確性,但無法保證內容的完整性、準確性或即時性且不構成法律、醫療或財務建議。若您發現本網站有任何錯誤、過時或具爭議之資訊,歡迎透過下列聯絡方式告知,我們將儘速審核並處理。如果你發現文章內容有誤:點擊這裡舉報。一旦修正成功,每篇文章我們將獎勵100元消費點數給您。如果AI文章內容將貴公司的資訊寫錯,文章下架請求,敬請來信(商務合作、客座文章、站內廣告與業配文亦同):[email protected]





