Vibe Coder

資料庫設計基礎:資料表、欄位型別與 Supabase CRUD

資料庫設計圍繞資料表、欄位、主鍵、外鍵、索引五個核心概念展開,正確的欄位型別很重要,例如金額要用 numeric 而不是 float,時間要用 timestamptz,ID 建議用 uuid。AI 生成的 Schema 常見缺 created_at、金額用 float、沒索引、沒 NOT NULL、沒開 RLS 五個問題,設計資料表時要主動檢查。
資料庫設計基礎:資料表、欄位型別與 Supabase CRUD

資料庫設計基礎:資料表、欄位型別與 Supabase CRUD

資料結構決定一切:欄位設計錯了,查詢就慢;關係設計錯了,之後要遷移資料非常痛苦,有時候比重寫程式還難。現在用 Supabase 可以直接用介面建資料表,不需要自己管 PostgreSQL 伺服器,但 AI 生成的 Schema 不一定是最好的設計,懂了基礎才能判斷哪裡需要調整。這篇帶你把資料庫設計的核心概念一次搞懂。

你將學到什麼

關聯式資料庫核心概念

資料表、欄位、資料列、主鍵、外鍵、索引,六個名詞一次看懂。

欄位型別怎麼選

金額、日期、ID 各自該用什麼型別,避開浮點數精度陷阱。

基本 SQL 與 Supabase CRUD

建表、新增、查詢、更新、刪除,SQL 語法和 Python SDK 兩種寫法。

AI 生成 Schema 常見問題

五個最常出現的漏洞,設計完資料表要逐一檢查。

關聯式資料庫核心概念

usersid (PK)emailnameordersid (PK)user_id (FK)amountcreated_at1
一個 user 可以有多筆 order,關聯靠外鍵撐起來。
概念說明例子
資料表(Table)存放一種類型資料的容器users 表、posts 表、orders 表
欄位(Column)資料的一個屬性name、email、created_at
資料列(Row)一筆完整的記錄一個使用者的所有資料
主鍵(Primary Key)唯一識別每筆記錄的欄位id(通常是自動遞增整數或 UUID)
外鍵(Foreign Key)指向另一個資料表主鍵的欄位posts.user_id 指向 users.id
索引(Index)加速查詢的資料結構在 email 欄位建索引,查詢更快

常見資料類型選擇

資料建議類型理由
使用者 IDuuid全域唯一,不會被猜測到,Supabase 預設
一般整數int4 或 bigint計數、數量用整數,bigint 適合大數
金額numeric(10,2)浮點數有精度問題,金額要用 numeric
短文字varchar(255)email、名稱等有長度上限的文字
長文字text文章內容、描述等無長度上限的文字
日期時間timestamptz帶時區的時間戳,避免時區問題
布林值boolean是否已讀、是否啟用等二元值
JSON 資料jsonb結構不固定的資料,比 json 更快更彈性
金額絕對不能用 floatfloat 有浮點精度問題,0.1 加 0.2 不會精確等於 0.3。金額、稅率、匯率這類需要精確計算的數字,必須用 numeric(PostgreSQL)或 DECIMAL(MySQL)。

基本 SQL 操作

建立資料表:

-- 建立 users 資料表
CREATE TABLE users (
    id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
    email varchar(255) UNIQUE NOT NULL,
    name varchar(100) NOT NULL,
    created_at timestamptz DEFAULT now()
);

-- 建立 posts 資料表(有外鍵)
CREATE TABLE posts (
    id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
    user_id uuid REFERENCES users(id) ON DELETE CASCADE,
    title varchar(255) NOT NULL,
    content text,
    created_at timestamptz DEFAULT now()
);

基本 CRUD:

-- 新增
INSERT INTO users (email, name) VALUES ('j@x.com', 'Joan');

-- 查詢(JOIN 兩張表)
SELECT u.name, p.title
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE u.email = 'j@x.com';

-- 更新
UPDATE users SET name = 'Joan Chen' WHERE email = 'j@x.com';

-- 刪除
DELETE FROM users WHERE id = '...uuid...';

用 Supabase 做 CRUD

Supabase 提供 Python SDK,讓你不用寫 SQL 就能操作資料庫。

from supabase import create_client
import os

supabase = create_client(
    os.getenv("SUPABASE_URL"),
    os.getenv("SUPABASE_KEY")
)

# 查詢
result = supabase.table("users").select("*").eq("email", "j@x.com").execute()

# 新增
result = supabase.table("posts").insert({
    "user_id": user_id, "title": "Hello", "content": "..."
}).execute()

# 更新
result = supabase.table("users").update({"name": "Joan Chen"}).eq("id", user_id).execute()

# 刪除
result = supabase.table("posts").delete().eq("id", post_id).execute()

AI 生的 Schema 常見問題

問題症狀改善方式
沒有 created_at無法知道資料建立時間每張表加 created_at timestamptz DEFAULT now()
金額用 float計算有精度誤差改用 numeric(10,2)
沒有索引資料量大後查詢很慢常用查詢欄位(如 email、user_id)加索引
沒有 NOT NULL必填欄位卻可以是空值必填欄位加 NOT NULL
沒有開 RLS任何人可讀取所有資料每張表加 ENABLE ROW LEVEL SECURITY

延伸學習

把這篇文章分享給需要的人FacebookLINEThreadsX

常見問答

什麼是主鍵和外鍵?
主鍵(Primary Key)是唯一識別每筆記錄的欄位,通常用自動遞增整數或 UUID。外鍵(Foreign Key)是指向另一個資料表主鍵的欄位,用來建立兩張表之間的關係,例如 posts 表的 user_id 指向 users 表的 id。
為什麼金額不能用 float?
float 有浮點數精度問題,0.1 加 0.2 不會精確等於 0.3。金額、稅率、匯率這類需要精確計算的數字,必須用 PostgreSQL 的 numeric 或 MySQL 的 DECIMAL,否則長期累積會出現對不上帳的誤差。
AI 生成的 Schema 常見有哪些問題?
常見五個問題:沒有 created_at 導致無法知道建立時間;金額用 float 造成精度誤差;沒有索引導致資料量大後查詢變慢;必填欄位沒加 NOT NULL;以及沒有開啟 RLS 導致任何人都能讀取所有資料。
Supabase 可以不寫 SQL 操作資料庫嗎?
可以。Supabase 提供 Python SDK,用 supabase.table("users").select("*") 這類寫法就能完成查詢、新增、更新、刪除,不需要手寫 SQL 語法,對不熟悉 SQL 的人很友善。