「不是工程師」關聯式資料庫正規化是什麼? 先從第一正規化(1NF)開始吧!(database normalization, Primary Key - PK)
資料庫設計很難?都不實作練習當然難!先用這簡單的範例來了解吧!
此文章也有影片介紹,可以搭配影片一起學習!
「不是工程師」後端服務的根基,淺談SQL關連式資料庫 RDBMS
「不是工程師」關聯式資料庫正規化是什麼? 先從第一正規化(1NF)開始吧!
「不是工程師」外鍵Foreign key(FK)是什麼?從第二正規化(2NF)去除冗余資料談起吧!
「不是工程師」可以邏輯推斷出來就不要多加欄位?淺談資料庫第三正規化(3NF)
最多人用的關聯性資料庫 - MySQL 相關文章:
MySQL要怎麼念?淺談MySQL資料庫與MariaDB的歷史緣由
在關聯式資料的世界裡,其實DB table就像是一連串複雜的Excel表格,
在關聯式資料的世界裡,其實DB table就像是一連串複雜的Excel表格,
資料庫正規化是關聯式資料庫(Relational Database)的概念,NoSQL基本上沒有這個概念,畢竟NoSQL光是JSON形式的儲存就已經違反本文標題的第一正規化(1NF),因此設計理念、使用概念、目的、優勢劣勢都截然不同。需要搭判使用情境來判斷。
於是Edgar Frank Codd在1970年提出了資料庫正規化(database normalization或是稱標準化)的概念,目的是減少資
相信大家都有使用過Excel記帳的概念,
user | date | pay | item | shop |
小明 | 9/30 | 100, 200 | 螺絲, 軸承 | 好記 |
小華 | 10/1 | -200 | 廠商退款 | 興記 |
如果你英文苦手的話
user : 使用者
date: 日期
pay: 付款
item: 物件
shop: 商店
後面會用到的
key: 鑰匙
value: 值
這樣的Excel資料表上看似合理,
這邊指的是pay 出現了"100, 200"的值,而item出現了"螺絲, 軸承"這樣的兩個值於同一個欄位內。如果對於寫程式已經有一點概念的同學應該會發現應用層面的問題。
如果今天要紀錄100這樣的數字,我們可以使用Integer(整數 Int), 但是要處理"100, 200", 我們則必須使用Array 陣列紀錄成[100, 200] 或是直接用String 字串 "100, 200"紀錄。用字串絕對是不合理的做法,這樣沒辦法加總。如果用陣列的話,再加總的時候必須要判斷為Int或是Array,如果是Array就必須補上個迴圈(很多函式也只是把迴圈包起來而已,內部進行的還是迴圈,例如map)。
這樣很容易會讓應用層程式邏輯變複雜許多,而且沒必要。
更不用說正確正規化後可以讓資料庫幫你做加總而不需再應用層實作。
而第一正規化裏最重要的概念有兩個:定義主鍵值(primary key)以及單一值
先來整理值吧,從該表上可看到 pay 與item上都有著多筆資料在同一欄位中紀錄的問題,所以我們先把表格重新攤開
user | date | pay | item | shop |
小明 | 9/30 | 100 | 螺絲 | 好記 |
小明 | 9/30 | 200 | 軸承 | 好記 |
小華 | 10/1 | -200 | 廠商退款 | 興記 |
這樣就達到每一個對應的key裡都只有一個Value,
這時候就是第一正規化最重要的概念—「定義主鍵值 Primary Key」
所以我們來幫這張表上加上主鍵值吧,小編使用每一筆記帳的”順序
id | user | date | pay | item | shop |
1 | 小明 | 9/30 | 100 | 螺絲 | 好記 |
2 | 小明 | 9/30 | 200 | 軸承 | 好記 |
3 | 小華 | 10/1 | -200 | 廠商退款 | 興記 |
加上去後一切就清楚明瞭許多,不管是新增、查找或刪除,
這邊原作者其實是寫 post_id 而非 id,校正小編修改成id。原因是因為關聯性資料庫的欄位column是屬於某一個Table之下。如果今天Table已經叫Post的形況下,其實是不需要取名primary key叫做post_id的,直接叫"id"即可。
在有一些ORM系統裡面(例如Ruby on Rails),預設Table name + "id"是用於Foreign Key的。當然這並不是絕對,只是校正小編認為這樣比較直覺。
另外一提,如果你在關聯性資料庫存JSON基本上就是違反了第一正規化(1NF),但是違反不見得就是"死刑",這點會在以後的文章探討。
雖然用系統自動增長的純數字,當作主鍵值是一個不錯的選擇,
id不用流水號的原因可能很多,不同目的的Table表其實可以使用不同的設計。流水號其中一個優勢為可以直接看ID看出大概有多少筆資料,ID不重複的概念也很容易理解。但是如果直接顯示可能會被猜到商家營業額(單日多少單號),或是網路爬蟲很好爬 (一個迴圈掃到底)。
UUID / GUID 等雜湊值雖然可以有效的解決這些問題,但是基本上字數就比較多,多少會影響比對速度與儲存空間,也很難去記憶。試想當你是客服人員,請客戶回覆你訂單號碼的時候,他給你請幫我查 "ec48edee-1f5a-48f1-9a32-845e9db7cd03"。 他光打字就恨死你了,你如果用電話接聽你也會恨死工程師。
不過這些都是很簡單可以解決的問題(多開column 或是 用日期 + 部分hash值),但是如果開資料表的人沒注意到這點小地方,後面維護以及使用的人會異常痛苦。
不知道眼尖的同學們有沒有發現,這樣紀錄的方式其實很容易出現大量的重複資料。如果重複資料的資訊量又很大的話,不就很佔空間?並且在更改的時候會十分麻煩,試想一個有10萬筆紀錄的使用者改名,要手動複製貼上嗎?
就讓小編在下一篇文章介紹第二正規化,來解決大家的疑惑。
接下來廣告一下,如果對資料庫設計和網站架設有興趣的話,可以考慮參加我們課程:
從零開始的SQL語法與資料庫設計 - 以MySQL來攻略 是MySQL的初階至中階課程,除了基本SQL語法的教學外,也包含資料庫設計理念與實作。對於一直搞不懂資料庫的同學會有相當的幫助喔!
快速開發,從頭教起的Ruby on Rails後端之旅 是後端網站APP課程開發課程,課程中包含詳細的購物網站架設與資料庫設計教學,內容涵蓋SQLite, MySQL, PostgreSQL,以及最後的募資平台(含資料表設計),可以參考看看喔!
最後,如果你喜歡我們的文章,別忘了到我們的FB粉絲團按讚喔!!