本系列文將會以最淺顯好懂的方式說明相關議題,已經了解的朋友或許也能從中知悉一些脈絡細節,希望這些文章能讓讀者們有所收穫。
Relational Database
--------------------------------------------------------------
資訊系統一定會有資料,資料動輒萬筆起跳,想像一下,現實世界裡你要怎麼擺放一萬顆螺絲釘,才能讓你在你要放入新的螺絲釘跟找到某顆螺絲釘的時候,都快速有效確實呢?關聯式資料庫就是個大概已經成熟了超過十年以上的解,剛好有同事問,來介紹一下簡單的例子吧。
以早年(?)網站教學書本最喜歡用的論壇為例好了,首先你會需要紀錄使用者的紀錄,在資料庫裡這樣的單位叫Table(表格),其中有一個很重要的欄位叫key,他將會作為table裡的每一筆資料的識別唯一用途:
使用者table | ||||
Key | Name | 密碼 | 建立日期 | ... |
1 | 人1 | 碼1 | 2018/10/08 | |
2 | 人2 | 碼2 | 2018/10/08 |
論壇所以還要有文章table
文章table | ||||
Key | Title | 本文 | 建立日期 | ... |
1 | 文章1 | 本文1 | 2018/10/08 | |
2 | 文章2 | 本文2 | 2018/10/08 |
而這時候怎麼知道哪篇文章的作者是誰?如果這個議題是1對1,也就是說一個作者只有一篇文章,一篇文章也只有一個作者,那麼下面兩種方式其實都可以(只需要使用其中一種),表示了使用者1是文章1的作者、使用者2是文章2的作者
使用者table | |||||
Key | 文章Key | Name | 密碼 | 建立日期 | ... |
1 | 1 | 人1 | 碼1 | 2018/10/08 | |
2 | 2 | 人2 | 碼2 | 2018/10/08 |
文章table | |||||
Key | 使用者Key | Title | 本文 | 建立日期 | ... |
1 | 1 | 文章1 | 本文1 | 2018/10/08 | |
2 | 2 | 文章2 | 本文2 | 2018/10/08 |
這其中,第二行的(文章key/使用者key),又被稱為外來鍵(foreign key),對應到其他table的key
BUT,你知我知獨眼龍也知道,文章跟作者的關係不是1對1,而是1對多,一個作者可以有多篇文章,但一篇文章只有一個作者,所以就只能把外來鍵加在文章那邊,表示了使用者1是文章1的作者、使用者2是文章2、3的作者
文章table | |||||
Key | 使用者Key | Title | 本文 | 建立日期 | ... |
1 | 1 | 文章1 | 本文1 | 2018/10/08 | |
2 | 2 | 文章2 | 本文2 | 2018/10/08 | |
3 | 2 | 文章3 | 本文3 | 2018/10/08 |
那麼如果要記錄每篇文章把哪些使用者看過呢?這是一個多對多的關係,一個使用者可以看過不只一篇文章,一篇文章也能夠被不只一個使用者看過,這時候就無法只使用兩張表紀錄,需要第三張表,第一篇文章被使用者2、3看過,第二篇文章被使用者1看過,第三篇文章被使用者2看過。
使用者_文章table | |||
文章Key | 使用者Key | 建立日期 | ... |
1 | 2 | 2018/10/08 | |
2 | 1 | 2018/10/08 | |
3 | 2 | 2018/10/08 | |
1 | 3 | 2018/10/08 |
以上例來說使用者Table跟文章Table其實有不只一種關聯(作者-文章,讀者-文章),能不能一起處理?或是再加一種關聯好了,現在還想要紀錄哪些使用者按過文章讚,如下所式
使用者_文章table | ||||
文章Key | 使用者Key | 種類 | 建立日期 | ... |
1 | 2 | 看過 | 2018/10/08 | |
2 | 1 | 看過 | 2018/10/08 | |
3 | 2 | 看過 | 2018/10/08 | |
1 | 3 | 按讚 | 2018/10/08 | |
1 | 2 | 按讚 | 2018/10/08 |
這其中比較微妙的是,以上所看到都是共用的欄位,但當你一張表開始記了太多不同的資訊時候(學術用語叫不夠正規化),就會有些問題,比如上面的按讚如果改成打賞,而又需要紀錄打賞金額呢?你就會在一張表中出現大量空值欄位
使用者_文章table | |||||
文章Key | 使用者Key | 種類 | 金額 | 建立日期 | ... |
1 | 2 | 看過 | x | 2018/10/08 | |
2 | 1 | 看過 | x | 2018/10/08 | |
3 | 2 | 看過 | x | 2018/10/08 | |
1 | 3 | 打賞 | 50 | 2018/10/08 | |
1 | 2 | 打賞 | 40 | 2018/10/08 |
另外有一個常見的設計,當你一張表太長的時候你可能會把同一個key的資料拆分,比如你今天使用者的資訊越記越多,當你有一個使用者會員卡(?)你可能就可以分開來,但是兩邊的key基本是保持1對1的關係
使用者table | ||||
Key | Name | 密碼 | 建立日期 | ...(500行了,不想加在這了) |
1 | 人1 | 碼1 | 2018/10/08 | |
2 | 人2 | 碼2 | 2018/10/08 |
會員卡table | |||
Key | 使用者key | 會員卡等級 | 會員卡日期 |
1 | 1 | 1 | 2018/10/08 |
2 | 2 | 1 | 2018/10/08 |
這裡有一種比較不好的情況是,當你覺得每次拿到會員卡還要去關聯使用者很麻煩,想把使用者的資料放到會員卡的時候
會員卡table | ||||
Key | 使用者key | 會員名稱 | 會員卡等級 | 會員卡日期 |
1 | 1 | 姓名1 | 1 | 2018/10/08 |
2 | 2 | 姓名2 | 1 | 2018/10/08 |
你會覺得這樣拿出來(查詢)的時候簡單很多,你只需要查會員卡這張表,但你有想過你這樣放進去(修改)的時候你就要修改兩處,如果你忘了修改兩處更可怕,兩邊的資料就不一致了。
最神秘的設計出現了,當某些時候想不開不想開新表時候就會出現
使用者阿哩阿砸table | |||||||
Key | 使用者key | 對應種類 | 會員卡key | 會員卡日期 | 文章key | 打賞 | ... |
1 | 1 | 會員卡 | 1 | 2018/10/08 | x | x | |
2 | 1 | 作者 | x | x | 1 | x | |
3 | 2 | 會員卡 | 2 | 2018/10/08 | x | x | |
4 | 2 | 打賞 | x | x | 1 | 20 | |
5 | 1 | 打賞 | x | x | 2 | 5 |
看出上面記了什麼了嗎?1號使用者有一張會員卡1、1號使用者是文章1的作者、1號使用者打賞了文章2五塊,二號使用者有一張會員卡2、二號使用者打賞了文章1二十塊,注意,這已經是我簡略了的版本,可以簡單的想像會有打賞日期、文章發表日期等等,這張表就會又肥又雜,雖然好像遇到什麼問題的時候新增一個對應種類就好,但這樣超級不正規化,實在非常有失關聯式資料庫的意義(要不然就直接用NoSQL阿XD)。上表有時候可能會簡化成下表,利用某些欄位在不同種類其實代表不同意思來處理,但還是很肥啦
使用者阿哩阿砸table | ||||||
Key | 使用者key | 對應種類 | 外來key | 該種類日期 | 打賞 | ... |
1 | 1 | 會員卡 | 1 | 2018/10/08 | x | 少 |
2 | 1 | 作者 | 1 | 2018/10/08 | x | 一 |
3 | 2 | 會員卡 | 2 | 2018/10/08 | x | 點 |
4 | 2 | 打賞 | 1 | 2018/10/08 | 20 | 點 |
5 | 1 | 打賞 | 2 | 2018/10/08 | 5 | 點 |
-------------------------------------------------------------------------------------------------------
它:「我愛寫程式ㄟ!」
我:「你...愛寫程式?」
它:「是阿!」
我:「你...愛用程式解決問題?愛寫出被大家所使用的程式?愛能夠用程式改變世界的力量?」
它:「沒錯!你說得太...」
我:「你愛日以繼夜焚膏繼晷的寫程式?你愛無法離座坐到屁股長痔瘡的寫程式?你愛寫程式愛到奮不顧身?」
它:「你...」
我:「你愛想破頭想到拿頭去撞牆想到掉光頭髮的寫程式?你愛被時程、需求、主管、客戶追著跑的寫程式?你愛寫程式即使程式不愛妳?」
我:「你愛你明明知道這樣不是好的寫法卻仍然得這樣寫?你愛維護別人寫出來的爛程式?你愛聽不懂的主管胡說八道該怎麼寫?」
它:「你在說什麼東西啦!你也沒有這樣子阿!」
我:「是阿,所以我不愛寫程式。」
它:「你懂不懂寫程式阿?」
我:「:)」