iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

Day8_要怎麼把資料記錄下來?用資料庫來保存紀錄吧

前言

Day6 先把 User Story 畫成 UI 草圖,Day7 再把按鈕背後的判斷整理成流程圖。走到這裡,會遇到一個很實際的問題:使用者建立的帳號、專案與 Task,到底要存在哪裡?如果程式關閉或伺服器重新啟動後,資料就跟著消失,前面設計的畫面和流程也無法運作。

資料庫會把需要長期保存的資料記錄下來,並在新增、查詢或修改時維持一致。這篇先認識關聯式資料庫的基本概念,下一篇再把它們套用到專案管理網站的 Schema 設計。

大綱

  1. 什麼是「關聯式資料庫」
  2. 為什麼叫「關聯式」
  3. 用生活中的例子理解
  4. Table、Row、Column 是什麼
  5. Primary Key 是什麼
  6. Foreign Key 怎麼連接資料表
  7. 用一個完整的購物網站來看
  8. 為什麼不要全部放同一張表
  9. 資料表之間有哪些關係
  10. SQL 與資料庫管理系統有什麼不同
  11. 回到專案管理網站
  12. 最重要的概念整理

1. 什麼是「關聯式資料庫」?

關聯式資料庫(Relational Database)會把資料分成一張張資料表,再用欄位描述每筆資料的內容。不同資料表也能透過共同的識別值建立關係。

以購物網站為例,系統通常會分開保存:

  • 會員資料
  • 商品資料
  • 訂單資料
  • 付款資料

如果把這些內容全部塞進同一張表,會員姓名、Email 與商品資訊會隨著每筆訂單不斷重複。關聯式資料庫會依資料的用途拆成不同表格,需要時再把它們組合起來。

它的外觀看起來有點像 Excel,但用途不太一樣。Excel 適合人工整理與計算;關聯式資料庫則能定義資料型別、唯一性與表格之間的關係,也能讓多人或多個程式同時讀寫資料。

2. 為什麼叫「關聯式」?

先看兩張表。第一張記錄會員:

會員編號 姓名 Email
1 小明 ming@test.com
2 小華 hua@test.com
3 小美 mei@test.com

第二張記錄訂單:

訂單編號 會員編號 金額
1001 1 500
1002 1 800
1003 2 1200

兩張表都有「會員編號」。訂單 1001 的會員編號是 1,回到會員表便能找到小明,因此可以判斷這張訂單屬於小明。

小明(會員編號 1)
├── 訂單 1001
└── 訂單 1002

小華(會員編號 2)
└── 訂單 1003

不過,「關聯式」這個名稱不只是指資料表彼此有關係。在關聯模型中,Relation 是一組結構相同的資料;初學時可以先近似理解成一張 Table,表內的每一列則是一筆資料。會員表與訂單表都是 Relation,再透過 Key 對應彼此的資料。

換句話說,資料先以表格結構保存,再利用共同欄位建立連結。程式因此能從訂單找到會員,也能查出某位會員的所有訂單。

3. 用生活中的例子理解

可以先把關聯式資料庫想成公司的 Excel 活頁簿,每個 Sheet 各自保存一類資料。

Sheet 1:員工

員工編號 姓名 部門編號
E001 Louis D01
E002 Amy D02
E003 Kevin D01

Sheet 2:部門

部門編號 部門名稱
D01 資訊部
D02 財務部

Sheet 3:專案

專案編號 專案名稱 負責人編號
P001 網站改版 E001
P002 ERP 導入 E003

員工表中的 D01 可以對應到資訊部;專案表中的 E001 則對應到 Louis。沿著這些編號查找,就能回答「Louis 在哪個部門」或「網站改版由誰負責」。

網站改版(P001)
└── 負責人 E001
    └── Louis
        └── 部門 D01
            └── 資訊部

表格只保存必要的編號,不需要在每個專案內重寫員工姓名與部門名稱。當 Louis 調到其他部門時,只要修改員工表的一筆資料,專案紀錄仍能指向同一位員工。

4. Table、Row、Column 是什麼?

剛開始接觸資料庫,會先遇到 Table、Column 與 Row。以下用會員資料說明。

Member Table

MemberId Name Email Age
1 Louis louis@test.com 30
2 Amy amy@test.com 25
3 Kevin kevin@test.com 32

Table:資料表

Table 是保存同一類資料的表格,例如 Member 用來保存會員。實際系統通常會有多張資料表,各自負責帳號、專案或工作項目等資料。

Column:欄位

Column 是表格直向的欄位,用來定義一筆資料要記錄哪些屬性。Member 表中的 MemberIdNameEmailAge 都是 Column。

欄位除了名稱,也會設定資料型別與限制。例如 Age 可以使用整數型別,Email 可以限制長度;必要欄位則不允許空值。這些規則能在資料寫入時先擋下不合理的內容。

Row:資料列

Row 是表格橫向的一筆紀錄。以下內容就是一位會員的完整資料:

1 | Louis | louis@test.com | 30

可以把三個名詞記成:

Table:保存哪一類資料
Column:這類資料有哪些屬性
Row:實際保存的一筆資料

5. Primary Key 是什麼?

同名的人很常見。假設會員表裡有三位王小明,只靠姓名無法確定要查詢或修改哪一筆資料。

MemberId Name
1 王小明
2 王小明
3 王小明

Primary Key(主鍵,簡稱 PK)用來唯一識別一筆資料。上表的 MemberId 就是主鍵,因此 MemberId = 2 只會對應到其中一位會員。

主鍵必須符合兩個基本條件:

  • 每一筆資料的主鍵值不能重複。
  • 主鍵不能是空值。

主鍵不一定只有一個欄位。有些資料會把兩個以上的欄位合在一起作為複合主鍵,例如選課紀錄可用 StudentId + CourseId 表示「某位學生選了某門課」。只要這組值能唯一識別一筆資料,就能作為主鍵。

把主鍵比喻成身分證字號很容易理解,但要留意:資料庫主鍵是系統用來辨識資料的值,不代表一定要存放真實身分證字號。實務上常使用自動產生的數字或 UUID,避免把具個資性質的欄位拿來當識別鍵。

6. Foreign Key 怎麼連接資料表?

Primary Key 可以辨識資料,Foreign Key(外鍵,簡稱 FK)則用來指向另一張表的資料。

Member

MemberId Name
1 Louis
2 Amy

Member 表中,MemberId 是 Primary Key。

Order

OrderId MemberId Amount
1001 1 500
1002 1 1000
1003 2 300

Order 表中,OrderId 是 Primary Key,而 MemberId 是 Foreign Key。Order.MemberId 指向 Member.MemberId,所以 Order.MemberId = 1 代表這張訂單屬於 Louis。

https://ithelp.ithome.com.tw/upload/images/20260907/201264877FXKXxz5HX.png

外鍵不只是方便查詢,也能保護資料一致性。若會員表沒有 MemberId = 99,資料庫可以拒絕新增一張 MemberId = 99 的訂單,避免出現找不到會員的孤兒資料。

7. 用一個完整的購物網站來看

購物網站除了會員與訂單,還需要商品與訂單明細。這幾張表的責任不同:會員表保存誰下單,商品表保存販售內容,訂單表記錄一次交易,訂單明細則保存這次交易買了哪些商品。

Member

MemberId Name
1 Louis

Product

ProductId ProductName Price
101 鍵盤 2000
102 滑鼠 1000

Order

OrderId MemberId
5001 1

OrderDetail

OrderId ProductId Quantity
5001 101 1
5001 102 2

沿著這些關聯,訂單 5001 可以解讀為:Louis 購買一個鍵盤與兩個滑鼠。

Louis(MemberId 1)
└── Order 5001
    ├── 鍵盤(ProductId 101)× 1
    └── 滑鼠(ProductId 102)× 2

OrderDetailOrderProduct 之間的中介表。它不只連接兩張表,還保存數量這個屬於交易的資訊。若還要保留成交時的單價,也可以在訂單明細加入 UnitPrice,因為商品日後調價時,舊訂單的成交金額不應跟著改變。

8. 為什麼不要全部放同一張表?

假設會員、訂單與商品全部放在一起:

訂單 會員姓名 Email 商品 商品價格
1001 Louis louis@test.com 鍵盤 2000
1001 Louis louis@test.com 滑鼠 1000
1002 Louis louis@test.com 螢幕 8000

Louis 的姓名與 Email 在每筆商品紀錄中重複。當 Email 改成 new@test.com,所有相關資料都得一起修改;只要漏掉一筆,同一位會員便會出現兩個 Email。

把資料拆成 MemberOrderOrderDetail 後,會員資料只需要保存一次,訂單只記錄 MemberId。修改會員 Email 時,只會動到 Member 表中的一筆資料。

這種設計可以減少三類常見問題:

  • 更新異常:同一份資料分散在多筆紀錄,修改時容易漏掉。
  • 新增異常:還沒有訂單時,卻無法單獨保存會員或商品。
  • 刪除異常:刪除最後一張訂單時,連會員資料也一起消失。

不過,拆表也不是越多越好。每張表都要有明確用途,並依資料生命週期與查詢方式決定是否拆分。下一篇會再談正規化與實際 Schema 設計。

9. 資料表之間有哪些關係?

資料表之間常見的關係有一對一、一對多與多對多。關係描述的是兩邊各自能對應幾筆資料。

一對一 One-to-One

會員 1 ───── 1 會員詳細資料

一位會員只對應一份詳細資料,一份詳細資料也只屬於一位會員。這類設計常用來把較少使用或有不同存取權限的資料分開保存。

一對多 One-to-Many

會員 1 ───── N 訂單

一位會員可以有多張訂單,但每張訂單只屬於一位會員。這是很常見的關係,外鍵通常放在「多」的那一方,因此 Order 表會保存 MemberId

多對多 Many-to-Many

學生與課程就是多對多:一位學生可以選多門課,一門課也能有多位學生。

關聯式資料庫通常會加入一張中介表,把多對多拆成兩個一對多:

Student 1 ── N Enrollment N ── 1 Course

Enrollment 可以使用 StudentIdCourseId 作為複合主鍵,避免同一位學生重複選同一門課。如果選課還要記錄學期或成績,這些欄位也會放在 Enrollment,因為它們描述的是「這次選課」,而不是學生或課程本身。


10. SQL 與資料庫管理系統有什麼不同?

資料庫與 SQL 不是同一件事。關聯式資料庫負責保存及管理資料;SQL(Structured Query Language,結構化查詢語言)則是我們操作資料庫時使用的語言。

例如,查詢所有會員可以寫成:

SELECT *
FROM Member;

新增、修改與刪除資料,則會使用 INSERTUPDATEDELETE。這些指令描述「要對資料做什麼」,資料庫管理系統負責執行並維護資料。

常見的關聯式資料庫管理系統包括:

  • SQL Server
  • PostgreSQL
  • MySQL
  • Oracle Database

它們大多支援 SQL,但在資料型別、函式與部分語法上仍有差異。本系列的專案會使用 SQL Server,因此後續範例會以 SQL Server 的行為為準。


11. 回到專案管理網站

這個系列要開發的是專案管理網站,需要保存帳號、專案、專案成員與工作項目。依照前面的概念,可以先整理成四張表:

https://ithelp.ithome.com.tw/upload/images/20260907/20126487GdTlr5lmQ0.png

一個帳號可以參與多個專案,一個專案也有多位成員,因此需要 ProjectMembers 保存兩者的多對多關係。TaskItems.ProjectId 表示工作項目屬於哪個專案,AssignedAccountId 則記錄指派對象。實際寫入工作項目前,後端還要確認指派對象確實是該專案的成員。

回頭看 Day6 的 Task 清單,畫面上的標題、狀態、交付期限與指派對象,都要從資料庫讀取。Day7 流程中的版本衝突、軟刪除和 Email 寄送紀錄,也各自需要資料配合。上面四張表只是先抓出主要實體,還不是完整的 Schema。

這裡先看資料如何分組與連接,不急著決定所有欄位。真正設計 Schema 時,還要回頭確認 User Story、資料生命週期與查詢方式。例如工作項目清單上的 checkbox 只用於當次批次選取,重新整理後就會消失,因此不需要存進資料庫。下一篇會繼續處理這些判斷。


12. 最重要的概念整理

先記住以下六個名詞,就能掌握關聯式資料庫的基本結構:

名詞 白話意思
Database 管理多張資料表與相關規則的系統
Table 保存同一類資料的表格
Column 定義這類資料要記錄哪些屬性
Row 實際保存的一筆資料
Primary Key 唯一識別一筆資料的欄位或欄位組合
Foreign Key 指向另一張表資料的欄位

把它們放在一起,可以得到以下結構:

Database
│
├── Member
│   ├── PK MemberId
│   ├── Name
│   └── Email
│
└── Order
    ├── PK OrderId
    ├── FK MemberId ──────> Member.MemberId
    └── Amount

關聯式資料庫會把不同用途的資料放進各自的表格,再透過 Primary Key 與 Foreign Key 建立關係。理解這個結構後,接下來學習 JOIN、正規化與 ER Model 時,就能知道每個工具是在解決什麼問題,而不是只記住一串名詞。

下一篇會回到 Project Management Web,從 User Story 找出 Entity、Attribute 與 Relationship,再把帳號、專案、成員和工作項目轉成實際的資料表設計。


上一篇
Day7_架構想好了,那流程怎麼操作呢,用流程圖說明一下
系列文
Codex的規格驅動開發 :30 天打造 .NET 內部專案管理系統9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言