瞻新資訊|網站設計、APP開發、UI/UX設計、LINE Bot開發

兩位專業人士在會議室對話,左側女性業主提出對話框問題「資料庫要怎麼設計,才不會後患無窮?」,右側男性顧問手指向白板,白板上有資料表、金鑰、連結、資料夾、齒輪、勾選等六個圖示以虛線相連

資料庫設計怎麼做才不會後患無窮?正規化、資料表關聯與主鍵外鍵規劃全解讀

作者|瞻新資訊 張安邦執行長(台大醫工背景・十年以上IT服務公司創辦人)

如果你正在規劃一個網站或系統——不管是會員登入、線上預約,還是內部的客戶管理系統——工程師遲早會跟你討論到「資料庫設計」這四個字。多數企業主聽到這裡通常會有兩種反應:一種是直接放棄理解,反正是工程師的事;另一種是點頭裝懂,心裡其實在想「不就是畫幾張表格嗎」。

資料庫設計真的不是畫幾張表格這麼簡單,它決定了這套系統以後好不好維護、加新功能會不會處處卡關、資料會不會兜不起來。這篇文章不會教你寫SQL——那真的是工程師的工作——但會用不需要任何程式背景就看得懂的方式,帶你搞懂資料庫設計在做什麼、幾個關鍵判斷點是什麼,以及最容易踩的坑有哪些。看完之後,你不用自己會設計,但至少聽得懂工程師在講什麼,也知道該問什麼問題。

如果你還不確定資料庫本身是什麼、跟資料庫管理系統有什麼差別,可以先看資料庫是什麼?從定義、種類到系統開發中的角色一次搞懂這篇打底;這裡不重複那些定義,直接從設計本身講起。

資料庫設計,其實是在幫資料「排隊」——先搞懂它在做什麼

先用一個你一定有經驗的畫面來理解:公司的檔案室。剛開業的時候,文件不多,隨便找個抽屜塞進去都找得到。但公司做大了、文件變多了,如果還是隨便塞,總有一天你會翻半天找不到某張合約,甚至同一份文件被抄了兩份、內容還兜不起來。

資料庫設計做的事,本質上就是「先想清楚要怎麼分類、怎麼擺,之後才不會亂」。差別只在於,資料庫處理的不是紙本文件,而是網站、系統背後那些會員資料、訂單紀錄、預約時段這類會不斷變動、不斷長大的資料。

實務上,資料庫設計通常分成三個階段:

  • 概念設計:先搞清楚「這個系統裡有哪些東西要被記錄」——客戶、訂單、商品這些「角色」,以及角色之間有什麼關係。這個階段還沒決定要用哪一套資料庫系統,純粹是把業務邏輯想清楚。
  • 邏輯設計:把上一步想清楚的「角色跟關係」,轉換成實際的資料表結構——決定每張表有哪些欄位、哪個欄位是這張表的身分證(主鍵)、表跟表之間怎麼關聯(外鍵)。正規化這件事,就是在這個階段發生的
  • 實體設計:把邏輯設計轉成資料庫系統(例如MySQL、PostgreSQL)真正看得懂的建表指令,同時決定索引、資料格式這些比較技術性的細節,這個部分完全是工程師的工作範圍。

拿檔案室來比喻:概念設計是先想「我要收哪幾類文件」;邏輯設計是決定「用什麼資料夾、子資料夾去分類,貼什麼標籤」;實體設計則是實際去買資料夾、貼標籤、排進櫃子裡。前面兩步想得越清楚,後面東西越好找、越不容易亂

概念設計階段通常會畫成一張圖,把角色跟角色之間的關係攤開來看,這跟系統開發常用來溝通整體結構的系統架構圖是同樣的道理——先用圖把系統內部的樣子畫出來,工程師與企業主才能對齊理解,不用等到程式都寫完才發現雙方想的不一樣。

簡單講一句:資料庫設計不是技術細節,是「先把業務邏輯想清楚,再轉換成資料結構」的過程。這也是為什麼很多設計問題,源頭其實不是工程師技術不好,而是需求訪談階段沒把業務邏輯問清楚。

三格連續畫面,中藥行老闆與客人問診對話、在空的百子櫃前貼標籤、以及裝滿藥材貼好標籤的成品百子櫃,對應概念設計、邏輯設計、實體設計三階段
資料庫設計的三個階段:概念設計、邏輯設計、實體設計

正規化:把資料拆乾淨,別讓同一件事出現在兩個地方

正規化在解決什麼問題

先講一個所有人都懂的情境:假設你公司的通訊錄,每次有人打電話來洽談新案子,行政都習慣把對方的公司名稱、地址、聯絡電話整組重新抄一次到那筆案子的紀錄裡。結果同一家客戶合作了五次,你的系統裡就有五份地址、五份電話——有一天客戶換了電話,你要記得去五個地方改,漏改一個,之後打錯電話的就是你自己

正規化要處理的正是這個問題:同一份資料只存一次,其他地方用「代號」去指向它,而不是整份複製。這個代號在資料庫的世界裡就叫「主鍵」,用主鍵去指向的動作叫「外鍵」,下一節會細講。

Microsoft Learn 官方文件對正規化的說明相當直接:正規化的目的是「保護資料並讓資料庫更有彈性,做法是消除重複資料以及不一致的相依性」。重複的資料除了浪費空間,最大的風險是「哪一份才是對的」——如果同一筆資料存在兩個地方,遲早會有一次忘記同步更新,兩邊資料就對不上了。

三個階段要懂到什麼程度

正規化在教科書裡分成好幾個階段,一般商業系統常用的是前三階段(1NF、2NF、3NF),不需要懂太深,但知道大概在講什麼,你就能聽懂工程師在說什麼

  • 第一階段(1NF):每個欄位只能放一個值,不能一個欄位塞「王小明、陳大華」兩個人名進去。白話說就是「一格只能填一件事」。
  • 第二階段(2NF):先符合第一階段,而且表裡每個非關鍵欄位,都要真的跟這張表的主角有關,不能夾雜跟別的東西有關的資料。
  • 第三階段(3NF):再更進一步,確保一張表裡的欄位彼此之間不會「拐個彎」互相依賴——例如一張訂單表裡同時存了「客戶編號」跟「客戶地址」,地址其實是跟客戶編號綁在一起,不該直接放在訂單表裡重複出現。

正規化不是分越細越好

這裡有個很多人會誤解的地方:正規化不是做得越徹底越好。教科書上其實還有更高階的正規形式(第四、第五正規化),但實務上很少用到——原因後面的常見錯誤會細講,這裡先記住一個判斷原則:多數商業系統的資料庫設計,做到第三正規化就已經足夠,再往上通常是學術上的完美,換來的是工程師和讀者都要花更多力氣理解一張越拆越細的資料表迷宮。

這個判斷原則不是憑經驗喊出來的口號。AWS 官方文件在說明資料庫結構設計時也提到類似的立場:關聯式資料庫的一般建議是移除資料重複與相依異常,只有在經過量測的工作負載確實需要、且有明確理由時,才考慮反正規化。換句話說,正規化是預設做法,反正規化是例外,不是反過來——不會有工程師因為「怕效能不好」就一開始跳過正規化,正確的順序永遠是先照3NF把結構設計乾淨,等真的遇到量測得出來的效能瓶頸,才針對那個瓶頸做局部反正規化。

💡 小提醒

聽到工程師說「這張表要正規化」,你不需要懂技術細節,只要記得一個檢查點:問他「這樣改之後,同一筆資料還會在兩個地方各存一份嗎?」——答案是「不會」,方向就是對的。

資料表關聯:一對多、多對多,表跟表怎麼「牽線」

搞懂正規化的「拆」之後,接下來要懂的是「拆開之後怎麼接回去」——這就是資料表關聯的工作,而牽線用的工具就是主鍵外鍵

主鍵很好理解:就像每個人的身分證字號,每一筆資料都要有一個獨一無二、不會重複的識別碼,用來確定「這是哪一筆」。外鍵則是在另一張表裡,寫上這個身分證字號,去指認「這一筆屬於哪個人」——而不是把那個人的所有資料重新抄一遍。

用一套常見的線上預約系統來說明:通常至少會有「客戶資料表」「服務項目表」「預約紀錄表」三張表。客戶資料表存客戶的姓名、電話;服務項目表存每項服務的名稱、時長;預約紀錄表則不重新抄一次客戶資料跟服務內容,而是各存一個「客戶編號」跟一個「服務項目編號」,分別指向前兩張表的主鍵。

這種一張表對應多筆另一張表資料的關係,叫做一對多:一個客戶可以有多筆預約紀錄,一個服務項目也可以被多次預約。IBM 官方文件在說明資料表關聯類型時提到,判斷關聯型態要先真正理解業務邏輯與實際的商業規則,也就是說,關聯怎麼設計,不是憑感覺,而是要回到「這件事在現實世界裡本來就是怎麼運作」去對照。

還有一種更複雜的關係叫多對多:假設同一套系統裡,一個服務項目可能需要搭配好幾個技師(技師A、技師B都能執行同一項服務),同時每個技師也能執行好幾種服務項目——這時候「服務項目」跟「技師」互相都是多對多,不能直接用外鍵把兩張主表接起來,要另外多開一張「中介表」(例如「技師服務對應表」),去記錄哪個技師會哪項服務。多對多關聯如果沒有這張中介表,資料庫幾乎無法乾淨地表達這種關係。

記住這個判斷點就好:一對多用外鍵直接對應就夠了;多對多一定要多開一張中介表,這是資料表關聯設計最容易漏掉、也最常導致後續要重新調整結構的地方。

左右對照畫面,左側一張處方箋以細線連到好幾格藥材抽屜示意一對多關聯,右側多張處方箋透過中間的登記簿交錯連到共用的藥材抽屜示意多對多關聯
一對多用外鍵直接對應,多對多需要一張中介表

主鍵要怎麼選?流水號 vs 業務欄位,這個決定會影響很久

主鍵要選什麼當識別碼,看似是小事,其實是資料庫設計裡影響最久遠的決定之一,因為之後所有的外鍵都要跟著它走。常見的兩種選法:

比較項目流水號(代理鍵)業務欄位(自然鍵)
定義系統自動產生的遞增編號,跟業務內容無關拿實際有意義的業務資料當主鍵,例如手機號碼、身分證字號、Email
穩定性高,一旦產生就不會變動較低,這些欄位未來仍可能異動(換手機號碼、Email)
直覺程度較低,單看編號看不出這是誰較高,一看欄位就知道對應到誰
異動風險幾乎不受業務資料變動影響業務欄位一旦變動,所有引用它的外鍵都要跟著調整
常見用法多數現代系統的預設做法需要額外的唯一值檢核(例如統一編號),但不建議直接當主鍵

流水號通常比業務欄位更適合當主鍵,因為業務欄位未來仍有可能變動,一旦變動,所有引用它的外鍵都要跟著調整,牽動範圍常常比想像中大。舉例來說,如果一開始拿客戶的手機號碼當主鍵,某天客戶換了門號,理論上你得把資料庫裡所有引用這支號碼的地方一併更新——這在資料量小的時候還能忍,資料量一大,就是整個系統要停機處理的規模。

比較務實的做法是:主鍵用流水號,業務欄位(例如統一編號、Email)另外加一個「不可重複」的檢核規則,兩者各司其職——流水號負責穩定識別,業務欄位負責確保現實世界裡不會有兩筆重複的客戶資料混進系統。

這幾個資料庫設計的常見錯誤,代價通常要等系統跑一陣子才會浮現

前面講的都是「該怎麼做」,這一節講「容易做錯的地方」——而且這幾個錯誤有個共通點:剛上線的時候幾乎看不出問題,通常要等資料量變大、系統用了一段時間之後,代價才會慢慢浮現

為什麼會這樣?原因其實不難理解:資料量還很少的時候,設計好壞在效能上幾乎感覺不出差異——不管有沒有正確建索引、正規化做得徹不徹底,資料庫查詢個幾百、幾千筆資料都是瞬間完成,使用者根本感覺不到差別。只有等資料量成長到一定規模,這些設計上的差異才會被放大成使用者感受得到的延遲,甚至系統卡頓。這也是為什麼很多企業主在系統剛上線、資料量還少的階段,很難單靠肉眼判斷這套系統的資料庫設計品質到底好不好——不是看不出來,是還沒到會被看出來的規模。

過度正規化——查一筆資料要join六張表

前面提過,正規化不是分越細越好。業界確實有真實案例:因為過度追求正規化,把資料拆得非常細,結果一個簡單的「查詢庫存數量」,程式要串連六張表才能拿到答案,查詢效能被嚴重拖慢。

多數商業系統的資料庫設計,做到第三正規化已經足夠,教科書上更高階的正規形式(第四、第五正規化)在一般商業應用裡很少真的用到。判斷原則很簡單:拆分的目的是為了「避免資料重複」,如果拆到連查一筆很常見的資料都要繞好幾層,就已經超出實務上該有的程度。

反正規化沒有同步機制——兩份資料兜不起來

有時候工程師會為了讓某個常用查詢跑得更快,刻意「反正規化」——也就是故意讓一部分資料重複存放,減少查詢時的join次數。這本身不是壞事,但如果沒有配套的同步機制,反正規化容易出現「程式改了正規化的來源資料、卻忘記同步更新那份重複副本」的資料不一致問題,結果就是系統裡兩個地方顯示的數字對不上,客服跟客戶各說各話。

正確的反正規化,通常會搭配資料庫層級的自動同步機制,確保來源資料一改,重複的那份副本也會跟著更新,而不是完全依賴工程師記得手動同步——人一定會忘記,機制不會。

外鍵沒建索引——看不見的效能地雷

這是一個連不少工程師剛入行時都容易忽略的細節。PostgreSQL 官方文件明確說明:定義外鍵約束時,並不會自動在該欄位建立索引,要不要建索引要看實際的查詢需求另外處理。也就是說,你在資料表之間設了外鍵關聯,看起來架構很完整,但如果沒有另外替這個外鍵欄位建索引,當系統需要頻繁查詢或刪除、更新關聯資料時,資料庫得一筆一筆掃過整張表去核對,效能會隨資料量增加而明顯變差。這個問題不會在測試階段的小資料量下顯現,通常要等資料量成長到一定規模才會被發現,屬於典型「等系統跑一陣子才浮現代價」的例子。

一張大表——把 Excel 思維直接搬進資料庫

這個錯誤特別容易發生在「原本用Excel管理資料、後來想升級成系統」的公司身上:因為過去習慣一張Excel表格什麼都塞——客戶資料、訂單狀態、備註、負責業務,全部擠在同一張表的不同欄位裡——結果資料庫也依樣畫葫蘆,做出一張什麼都放的「大表」,而不是依照正規化原則拆成客戶、訂單、商品這些各自獨立又互相關聯的資料表。

一張什麼都塞的大表,正是正規化想避免的問題本身:同一個客戶的姓名、電話,只要下了兩筆訂單,就會在這張大表裡重複出現兩次;哪天客戶電話真的換了,得去改所有這個客戶名下的每一筆紀錄,改漏一筆,資料就對不上。這種設計在資料量小的時候看起來「反正都在同一張表,查資料還比較方便」,但資料量一大,不只儲存空間浪費、更新維護困難,連查詢效能都會被拖累。

⚠️ 注意

如果你的公司過去一直用Excel管理資料,跟工程師溝通系統需求時,很自然會用「這欄放這個、那欄放那個」的Excel式思維去描述需求,這沒有問題,但要有心理準備:一份Excel常常會被拆成資料庫裡的好幾張表,這不是工程師把事情複雜化,而是資料庫設計本來就該這樣做,才能避免前面講的重複與不一致問題。

左右對照畫面,左側百子櫃多格抽屜各自獨立存放不同藥材並貼有標籤,右側一個大布袋將所有藥材混雜堆放在一起
正規化讓資料各自獨立存放,一張大表則什麼都塞在一起

沒想清楚未來擴充——新功能只能硬塞

最後一個常見錯誤跟技術關係較小、跟規劃關係較大:一開始設計資料庫時,只想著「現在」要什麼功能,完全沒有預留未來可能擴充的空間。一家企業一開始做官網,只是想放產品介紹,後來陸續加了會員登入、線上預約、購物車功能,每加一項,資料庫就要多幾張表、而且往往要跟既有的表建立新的關聯——如果最初設計時完全沒想過這些可能性,常常會出現「新功能硬塞進舊架構」的窘境,效能變差是小事,更麻煩的是資料之間的關聯開始變得混亂,難以維護。

下面這張表把五個常見錯誤整理成對照表,方便你檢查自己的系統有沒有中招:

常見錯誤典型徵兆怎麼避免
過度正規化查一筆很常見的資料,要串連很多張表才能拿到答案一般商業系統做到第三正規化(3NF)已足夠,不必追求更高階的正規形式
反正規化沒同步機制系統裡兩個地方顯示的同一筆資料對不上反正規化要搭配資料庫層級的自動同步機制,不能只靠人工記得手動更新
外鍵沒建索引資料量變大後,查詢或刪除/更新速度明顯變慢替常用查詢與刪改的外鍵欄位另外建立索引
一張大表同一筆客戶或業務資料,在表裡重複出現好幾次依正規化原則拆成客戶、訂單、商品等各自獨立又互相關聯的資料表
沒想清楚未來擴充每加一項新功能,都要在舊架構裡硬塞欄位或表格需求訪談時一併討論未來半年到一年可能會加的功能

⚠️ 注意

上面五個錯誤裡,前四個是技術面的問題,工程團隊有經驗通常能避開;最後一個「沒想清楚未來擴充」,責任其實不完全在工程師身上——這需要企業主在需求訪談階段,把未來半年到一年可能會加的功能一併講出來,讓資料庫架構預留合理的彈性。

早想清楚,比上線後回頭改划算很多

這五個錯誤講完,你可能會想:那如果真的設計錯了,之後還能改嗎?技術上多半可以,但代價通常比一開始想清楚高出不少。

用一個好理解的比喻:這就像蓋房子時,如果一開始沒把水電管線的位置規劃好,等牆都砌好、磁磚都貼好了才發現插座位置不對,要改就得打牆、重拉線,代價遠比施工前多畫一張配線圖高上好幾倍。資料庫設計也是同樣的道理——系統剛開始開發、資料量還小的時候調整結構,通常只是改幾張表的定義;等系統上線、資料量累積到一定規模之後才發現設計有問題,往往要牽動所有依賴這張表的程式邏輯,一併調整,耗費的時間通常是早期處理的好幾倍

這也是為什麼在系統開發的需求訪談階段,即使當下只需要基本功能,也值得多花一點時間跟技術團隊討論未來可能會加的功能,讓資料庫架構預留合理的擴充空間——這筆前期多花的時間,通常比後期回頭補救划算得多。資料庫設計只是整個系統開發過程裡的一環,如果想知道這個環節在整個開發流程裡處於什麼位置,可以參考系統開發生命週期:委外開發前,這套邏輯你要先懂這篇。

企業主不用自己會設計,但要懂得問對問題

看到這裡你應該已經發現,資料庫設計牽涉的判斷,其實比「畫幾張表格」複雜得多:要正規化到什麼程度、資料表之間怎麼牽關聯、主鍵要選流水號還是業務欄位、有沒有預留未來擴充的空間——這些判斷會實質影響一套系統之後好不好用、好不好維護。

你不需要自己會設計資料庫,但可以在跟工程團隊討論規格的時候,問這幾個問題:這張表未來半年可能會加哪些欄位、關聯設計有沒有考慮到多對多的情況、外鍵有沒有配對建索引、如果之後資料量變大,這個設計還撐不撐得住。問得出這幾個問題,你就已經比多數企業主更懂得怎麼把關資料庫設計的品質。想進一步了解資料庫在更大的資訊系統裡扮演什麼角色,也可以參考資訊管理系統到底在管什麼?不是資料庫,也不只是ERP這篇。

瞻新資訊在協助客戶做系統規劃開發時,資料庫架構的正規化程度、資料表關聯設計與未來擴充空間,一直是需求訪談階段就會納入討論的項目,而不是等系統上線後才回頭補強。

常見問題

資料庫設計是什麼意思?

資料庫設計是把系統的業務需求,轉換成實際資料表結構的過程,通常分成概念設計、邏輯設計、實體設計三個階段。核心工作包括決定資料要怎麼拆分(正規化)、資料表之間怎麼關聯(主鍵外鍵),以及未來要怎麼擴充,不是單純畫幾張表格這麼簡單。

資料庫正規化要做到第幾正規化(NF)才夠?

多數商業系統做到第三正規化(3NF)已經足夠。教科書上還有更高階的正規形式,但實務上很少用到,過度追求正規化反而可能讓簡單的查詢需要串連很多張表,拖慢系統效能。判斷原則是:拆分的目的是避免資料重複,不是拆得越細越好。

主鍵一定要用流水號(自動遞增ID)嗎?

不是強制規定,但流水號(代理鍵)通常比業務欄位(自然鍵,例如手機號碼、Email)更適合當主鍵,因為業務欄位未來仍可能變動,一旦變動,所有引用它的外鍵都要跟著調整。比較務實的做法是主鍵用流水號,業務欄位另外加唯一性檢核。

資料表之間的關聯要怎麼規劃?一對多跟多對多差在哪?

一對多是一張表的一筆資料,對應到另一張表的多筆資料(例如一個客戶有多筆預約紀錄),用外鍵直接對應即可;多對多則是兩邊都可以對應多筆(例如一項服務可以由多個技師執行,一個技師也能執行多項服務),這種情況需要另外建一張中介表,不能直接用外鍵把兩張主表接起來

資料庫設計後來還能改嗎?改的代價會很大嗎?

技術上多半可以調整,但代價通常比一開始就想清楚高出不少。系統剛開發、資料量還小時調整結構相對單純;等上線後資料量變大才發現設計有問題,往往要牽動所有依賴這張表的程式邏輯一併調整,耗費的時間通常是早期處理的好幾倍。

正規化跟查詢效能會不會衝突?

有可能,但通常不是正規化本身的問題,而是正規化程度沒抓好。過度正規化確實可能讓一個簡單查詢需要串連很多張表;反過來,如果為了效能刻意反正規化,又沒有配套的同步機制,則容易出現資料不一致的問題。實務上常見的做法是先照3NF正規化,等真的遇到明確的效能瓶頸,再針對那個瓶頸做局部反正規化,而不是一開始就為了怕變慢而跳過正規化

資料庫設計裡的「一張大表」問題是什麼?

指的是把原本該拆成客戶、訂單、商品等多張資料表的資料,全部塞進同一張表裡管理,通常發生在習慣用Excel管理資料、後來想升級成系統的公司身上。這種設計會讓同一筆客戶或業務資料在表裡重複出現好幾次,資料量小的時候看起來查資料方便,資料量一大,儲存空間、更新維護與查詢效能都會被拖累,是正規化原本就想避免的典型問題。

外包工程師設計資料庫,企業主該問什麼問題?

可以問幾個不需要技術背景也聽得懂答案的問題:這張表未來半年到一年可能會加哪些欄位、資料表之間有沒有多對多的關係、外鍵有沒有配對建索引、如果資料量變大這個設計還撐不撐得住。問得出這幾個問題,就已經能有效把關資料庫設計的品質,不用自己動手設計也能參與判斷。

參考資料

ℹ️ 關於本文

本文引用的官方文件內容以查閱當日(2026年9月1日)版本為準,各項技術文件與工具介面可能持續更新,實際請以原始來源的最新說明為準。文中對資料庫設計原則的說明屬一般性經驗整理,實際系統的最佳設計方式仍須視業務規模、資料量與使用情境個別評估,不構成對任何特定系統效能或維護成本的保證。

張安邦

關於作者|張安邦執行長

台灣大學醫學工程研究所背景,十年以上軟體開發經歷,領軍瞻新資訊有限公司(2010年成立),完成專案200+、涵蓋40~50+個產業。專長:網頁設計、APP開發、UI/UX設計、LINE Bot自動化、系統開發、資訊安全。