MODULE 6 · 資料模型 · 6-6

把世界變成表格與欄位

上一個 Part 你學會了「選哪個資料庫陣營」。選好之後,下一步是把現實世界翻譯成一張張表格。 Schema 是你 App 的藍圖,而每個欄位的「資料型態」是第一道守門員。這個 unit 帶你親手踩過四個最常見的型態陷阱: Float 精度、字串排序、Boolean 字串、時區,看懂 AI 給的 schema 哪裡會出包。

§1 · Schema 是藍圖

把一個真實的人,翻譯成一張表格

資料庫不認識「一個 Spotify 使用者」。它只認識欄位(column)跟一筆筆資料(row)。

現實世界:一位使用者
🎧
Mia
付費會員 · 台灣

點任一個屬性,看它對應到右邊表格的哪一欄。

📋 table: usersSCHEMA
id
INTEGER
display_name
TEXT
email
TEXT
is_premium
BOOLEAN
country
TEXT
1Miamia@x.comtrueTW
2Meimei@x.comfalseJP
目前 2 筆 row(每筆 = 一位使用者)
解剖同一張表,三個你會一直聽到的詞
🎧
Mia
mia@x.com
✦ 付費會員🇹🇼 台灣

這是 App 裡一位使用者的個人頁。資料庫不認識「畫面」,它只把這個人記成一張表裡的一橫列

SCHEMA · 整張表的藍圖idemailis_premiumcountry1mia@x.comtrueTW2mei@x.comfalseJP
Schema 藍圖 整張表的設計藍圖:有哪些欄位、各存什麼型態、有什麼規則。先把藍圖畫好,才開始往裡面裝一筆筆資料。
🔑VIBE CODER 秘訣
👀觀察
AI 幫你建表時,會直接決定「有哪些欄位、各是什麼型態」。它看不到你腦中的產品,只能用最常見的猜。
💬怎麼跟 AI 講
把實體講清楚:「我要一張 users 表,需要 email、是否付費、國家、註冊時間這幾個欄位,幫我各配一個適合的型態。」型態是接下來整個 unit 的重點。
§2 · 資料型態

型態圖鑑:每個欄位都要先講好存什麼

型態不只是分類,它是第一道守門員。選對了,髒資料寫不進來;選錯了,bug 等著你。

🔢INTEGER
存:整數
例:Instagram 貼文的愛心數
1204
💰DECIMAL
存:精確小數
例:Uber 這趟的車資
237.50
📝TEXT / VARCHAR
存:文字字串
例:YouTube 影片標題
"用 AI 三天做出一個 App"
BOOLEAN
存:true / false 兩種值
例:Spotify 是不是付費會員
true
🕐TIMESTAMPTZ
存:帶時區的時間點
例:這則貼文的發佈時間
2026-05-28T14:32:00Z
📦JSONB
存:巢狀 / 不固定結構
例:使用者的通知設定
{ "push": true, "email": false }

這是六種最常見的型態速查表。下面四段把最容易選錯的四個坑,各帶你親手踩一遍。

🔑VIBE CODER 秘訣
👀觀察
AI 很愛用 TEXT 通吃一切,因為「字串什麼都裝得下、最不會報錯」。但裝得下不代表正確,型態鬆掉了守門功能也跟著消失。
💬怎麼跟 AI 講
建表時主動點名:「金額用 DECIMAL 不要 FLOAT,時間用 TIMESTAMPTZ,開關用 BOOLEAN,手機號用 TEXT。」
§3 · 陷阱一:金錢

用 FLOAT 存錢,加一加就少了一塊錢

電腦用二進位存小數,0.1 沒辦法被精確表示。一筆筆加起來,誤差會浮出來。

購物車:(空的,點上面加入)
FLOAT浮點數存法
$0
整數分 / DECIMAL正確存法
$0.00
用「分」當整數存,最後才除以 100,永遠精確。
🔑VIBE CODER 秘訣
👀觀察
AI 產生的 schema 很常把價格寫成 price FLOATREAL。Demo 金額小看不出來,等到對帳、退款、累計營收才爆。
💬怎麼跟 AI 講
明確要求:「金額欄位用 DECIMAL(10,2),或在程式裡一律以整數『分』儲存,絕對不要用 FLOAT。」
§4 · 陷阱二:排序

把數字存成文字,排序就壞了

文字是「一個字一個字比」,所以「10」會排在「9」前面,因為第一個字 1 比 9 小。

這個欄位的型態是:
原始資料:9、10、100、2、30
ORDER BY 由小到大:
10
100
2
30
9
字串排序:10、100 跑到 2、9 前面了。如果這是商品價格或排行榜名次,使用者會看到亂掉的順序。
🔑VIBE CODER 秘訣
👀觀察
AI 為了「保險」常把編號、價格、版本號存成字串。平常看不出來,一旦 ORDER BY 就露餡。
💬怎麼跟 AI 講
「會拿來比大小或排序的欄位,用數字(INTEGER / DECIMAL)或時間型態,不要用字串。」
§5 · 陷阱三:開關

把開關存成字串 "false",程式以為是開著的

在程式裡,只要不是空字串,任何字串都算 true。所以字串「false」跟「0」其實都是「真」。

情境:is_notification_enabled(要不要推播通知)。資料庫裡這個欄位被存成下面其中一種。點選看程式怎麼判斷:
const value = "false"; // 字串
if (value) sendNotification();
判斷結果: 進入 if → 推播寄出(true)
😱 出事了:你存的是 "false",本意是「關閉」,但它是字串,程式判定為 true,通知照樣寄出去。這是超經典的 bug。
🔑VIBE CODER 秘訣
👀觀察
從表單、CSV、環境變數讀進來的「布林值」常常是字串。AI 寫的程式如果直接 if (value),字串 "false" 會被當成 true。
💬怎麼跟 AI 講
「這個欄位用真正的 BOOLEAN 型態;如果來源是字串,幫我明確轉換(例如 value === "true"),不要直接拿字串判斷。」
§6 · 陷阱四:時間

存一個沒時區的時間,全世界看到的都錯

直播在台北時間晚上 8 點開始。如果只存「20:00」這串字,東京、紐約的觀眾會以為是他們的當地 8 點。

📺 事件:跨年直播 · 主辦方在台北設定開始時間 2026-06-01 20:00
儲存方式:
觀看者在:
台北的觀眾打開 App,看到的開始時間是:
2026-06-01 20:00
台北本人剛好對,但這是運氣,不是設計。
🔑VIBE CODER 秘訣
👀觀察
AI 存時間常給沒時區的 DATETIME 或乾脆字串。本地測試(同一個時區)永遠看不出問題,上線遇到海外使用者才炸。
💬怎麼跟 AI 講
「時間欄位用 TIMESTAMPTZ(帶時區),一律以 UTC 儲存,只在顯示給使用者時才轉成他的當地時區。」
§7 · 防呆

型態之外,還能加規則把髒資料擋在門外

光有型態還不夠。NOT NULL、CHECK、DEFAULT 這些約束,讓不合理的資料根本寫不進來。

CREATE TABLE users (id, email TEXT NOT NULL, age INT CHECK (age >= 0), role TEXT DEFAULT 'user')
idemailagerole
1mia@x.com28admin
概念NOT NULL
這個欄位不准留空。email 沒填就拒收,不會留下半筆殘缺資料。
概念CHECK
自訂規則。age >= 0 擋掉負年齡,price > 0 擋掉負價格。
概念DEFAULT
沒給值時自動補。role 沒填就補 'user',省得每次都要寫。
🔑VIBE CODER 秘訣
👀觀察
AI 給的初版 schema 常只有欄位跟型態,沒有任何約束。能跑,但任何髒資料都塞得進去,資料庫失去守門功能。
💬怎麼跟 AI 講
「幫每個欄位補上合理的約束:必填的加 NOT NULL、有範圍的加 CHECK、有預設的加 DEFAULT。」唯一性(UNIQUE)跟關聯約束,下一個 unit 會講。
§8 · 小測驗

看到需求,你選得出對的型態嗎?

答錯不會鎖死,黃色提示會告訴你為什麼,換一個再試。

概念選型態的口訣
運算或排序的用數字 / 時間型態;金額用 DECIMAL;只有兩種狀態用 BOOLEAN;跨時區的時間用 TIMESTAMPTZ;不拿來算的號碼(電話、郵遞區號)用 TEXT。
答對 0 / 5 · 答錯可以一直重選,不會鎖死
Q1

💰商品價格(會用來加總、結帳)

Q2

使用者 email 驗證了沒

Q3

🕐貼文發布時間(使用者遍布全球)

Q4

📱手機號碼(可能有開頭 0、+886)

Q5

👍文章的按讚數

到這裡你已經會設計「一張表」了。但真實的 App 有很多表,它們要怎麼認得彼此?下一課(PK & FK)告訴你。

收尾 · Unit 2.1

你已經會設計『一張表』了

把型態直覺收進口袋,跟 AI 一起建表時隨時拿出來用。

型態直覺
  • · 看到「金額」想到 DECIMAL / 整數分,絕不用 FLOAT
  • · 看到「會排序的編號」想到別存字串
  • · 看到「開關」想到 BOOLEAN,小心字串 "false"
  • · 看到「時間」想到 TIMESTAMPTZ,存 UTC
  • · 看到 schema 沒約束,想到補 NOT NULL / CHECK / DEFAULT

型態是 schema 的第一根支柱,管「每一格裝什麼」。AI 常為了「能跑、寫得快」用 TEXT 通吃、不加約束,你現在看得懂也問得出對的問題。

但真實的 App 有很多張表,它們要怎麼認得彼此?下一課(PK & FK)講 schema 的第二根支柱:表跟表怎麼連。