一句話說明
AI 可以快速產生資料庫 Schema,但產生的結果經常有正規化問題、缺少索引、資料型別不精確,而且幾乎不會主動考慮敏感欄位加密和存取控制。把 AI 當成初版 Schema 的產生器,然後用人工審查補上它遺漏的部分。
AI 在資料庫設計中能幫什麼
用 AI 產生資料庫 Schema 在以下情境特別有價值:
從自然語言描述產生初版 Schema。你描述「我要做一個線上課程平台,有使用者、課程、章節、購買記錄」,AI 可以在幾秒內產生對應的資料表、欄位和關聯。對於 side project 或 MVP 階段,這比從零開始畫 ER Diagram 快很多。
既有 Schema 的檢查和優化建議。把 CREATE TABLE 語句貼給 AI,請它檢查有沒有正規化問題、缺少索引、命名不一致、或資料型別不恰當的地方。AI 在找這類「明顯但容易忽略」的問題上表現不錯。
產生 Migration 檔案。描述你要做的變更(「在 users 表新增 phone 欄位,可以是 NULL,並加索引」),AI 可以產生對應的 SQL migration,包括 up 和 down migration。
產生測試資料和 Seed 檔案。AI 可以根據 Schema 產生符合欄位型別和約束的假資料,省去手動造假資料的時間。
跨資料庫語法轉換。如果你要把 MySQL 的 Schema 轉成 PostgreSQL,AI 可以處理語法差異(例如 AUTO_INCREMENT 轉 SERIAL,ENUM 的處理方式不同)。
用 AI 產生 Schema 的完整 Prompt 範例
一個好的 Prompt 應該包含明確的需求、技術約束、和你對品質的期待。
基本版 Prompt:
幫我設計一個電商平台的資料庫 Schema。
需求:
- 使用者(支援 email 和手機號碼登入)
- 商品(有分類,支援多圖片)
- 訂單(包含多個商品,有運費和折扣)
- 購物車
技術要求:
- PostgreSQL 15
- 第三正規化
- 標籤和分類用關聯表
- 每個表都要有 id (UUID), created_at, updated_at
- 金額用 DECIMAL(12,2)
- 幫我加上適當的索引(外鍵、常用查詢欄位)
- 加上 COMMENT ON COLUMN 說明每個欄位的用途
進階版 Prompt(加入安全要求):
在上面的 Schema 基礎上:
- 標記哪些欄位是 PII(個人可識別資訊)
- 密碼欄位用 VARCHAR(72)(bcrypt hash 的長度)
- 手機號碼和 email 需要加 UNIQUE 約束
- 加上 deleted_at 欄位支援軟刪除
- 產生 Row Level Security (RLS) 政策,
讓使用者只能查看自己的訂單
- 產生對應的 CREATE INDEX 語句
知識檢測
讀完文章後,測試一下你對這個主題的理解。
AI 產生 Schema 的常見問題
正規化偏差
AI 產生的 Schema 傾向兩個極端。
過度正規化的例子:把地址拆成 countries、states、cities、districts、streets 五張表,每張都只有 id 和 name,然後用外鍵串起來。這在台灣的大部分應用中是不必要的複雜度。除非你的系統需要讓使用者從下拉選單選縣市鄉鎮(那這個設計才合理),否則一個 address TEXT 欄位加上 city 和 postal_code 就夠了。
正規化不足的例子:把 tags 直接存成逗號分隔的字串("python,fastapi,api")。這會讓「找出所有有 python 標籤的文章」這種查詢變成 LIKE '%python%' 的全表掃描,效能很差而且會誤中(例如 "cpython" 也會被撈出來)。正確做法是用 tags 表和 article_tags 關聯表。
另一個常見問題:AI 會把 JSON 欄位當成萬用解法。「商品的自訂規格?存 JSON。」「使用者的偏好設定?存 JSON。」JSON 欄位的問題是沒辦法加外鍵約束、索引效能差(PostgreSQL 的 GIN 索引有幫助但仍不如一般欄位)、而且 Schema 文件化困難。如果某個 JSON 欄位的結構是固定的,應該拆成獨立的欄位或表。
索引建議不足
AI 產生的 Schema 通常只會加上 Primary Key,不會主動建議其他索引。但查詢效能很大程度取決於索引設計。以下是經常需要加索引的情境:
外鍵欄位。orders.user_id 這種外鍵欄位在 JOIN 查詢中會頻繁使用,一定要加索引。PostgreSQL 不會自動幫外鍵加索引(MySQL InnoDB 會)。
經常用於 WHERE 條件的欄位。users.email(登入時查詢)、orders.status(篩選進行中的訂單)、products.category_id(分類頁面)。
排序欄位。如果你的列表頁用 created_at DESC 排序並分頁,這個欄位需要索引。
複合索引。如果你經常 WHERE user_id = ? AND status = ?,一個 (user_id, status) 的複合索引比兩個獨立索引更有效率。欄位順序很重要——選擇性高的欄位放前面。
用 Prompt 明確要求:
同時產生 CREATE INDEX 語句,
針對以下情境建議索引:
- 外鍵關聯查詢
- WHERE 條件常用欄位
- 排序和分頁欄位
- 需要的複合索引
請說明每個索引的用途。
資料型別選擇問題
AI 傾向使用通用的資料型別而非精確的型別,常見的問題:
VARCHAR(255) 萬用字串。AI 會把所有字串欄位都設成 VARCHAR(255),但 email 用 VARCHAR(320) 就夠了(RFC 5321 規範上限),手機號碼用 VARCHAR(20),用戶名用 VARCHAR(50)。精確的長度約束可以在資料庫層面防止異常資料。
FLOAT 存金額。浮點數有精度問題,0.1 + 0.2 在浮點數中不等於 0.3。金額應該用 DECIMAL(12,2) 或用最小單位整數存(例如以「分」或「角」為單位,$99.50 存為 9950)。
TEXT 存固定選項。訂單狀態(pending, paid, shipped, completed)、使用者角色(admin, editor, viewer)這類固定選項應該用 PostgreSQL 的 ENUM 或獨立的狀態表,而非用 TEXT 欄位存任意字串。
TIMESTAMP WITHOUT TIME ZONE。AI 產生的時間欄位經常是 TIMESTAMP,但在有多時區需求的系統中應該用 TIMESTAMP WITH TIME ZONE(PostgreSQL 的 TIMESTAMPTZ)。台灣的系統如果有海外使用者,忘了這點會造成時間顯示錯誤。
BOOLEAN 用 INTEGER 代替。有些 AI 用 TINYINT(1) 或 INTEGER DEFAULT 0 來存布林值,在 PostgreSQL 應該直接用 BOOLEAN。
Migration 安全
AI 產生的 migration 經常忽略大表的影響。以下是幾個常見的危險操作:
在百萬行的表上 ALTER TABLE ADD COLUMN ... NOT NULL DEFAULT '...'。在 MySQL 5.x 這會鎖表數分鐘(MySQL 8.0 改善了一些)。PostgreSQL 11+ 在加 NOT NULL + DEFAULT 時不會重寫整張表,但在舊版本一樣會鎖。
ALTER TABLE ... ADD UNIQUE INDEX 在大表上。建索引會鎖表,PostgreSQL 可以用 CREATE INDEX CONCURRENTLY 避免鎖表,但 AI 幾乎不會主動建議這個語法。
刪除欄位。AI 可能建議 ALTER TABLE DROP COLUMN,但如果有其他表的外鍵或觸發器依賴這個欄位,會直接報錯或級聯刪除。
安全的 migration 做法:
先加 nullable 欄位(不鎖表),再用批次更新填入預設值(每次更新 1000-5000 筆,中間 sleep 避免影響線上服務),最後才改成 NOT NULL。
每個 migration 都要有對應的 rollback(down migration)。AI 有時候會忘記寫 down migration,或寫了但遺漏了還原索引和約束。
在正式環境執行前,先在測試環境用相同資料量的資料庫測試 migration 的執行時間。可以用 pg_dump 做一份資料量相同的測試資料庫。
大型變更拆成多個 migration,每個可以獨立 rollback。
實際操作範例:用 AI 設計部落格系統
以下是一個完整的操作流程:
第一步:用 AI 產生初版 Schema。
設計一個部落格系統的 PostgreSQL Schema。
需求:使用者、文章(支援草稿和發布)、
分類(多對多)、標籤(多對多)、
留言(支援巢狀回覆,最多兩層)。
第二步:審查 AI 的輸出,檢查以下項目:
主鍵是用 UUID 還是自增 ID?如果是多個服務共用的資料庫,UUID 比較安全。如果是單體應用,自增 ID 效能較好。
留言的巢狀結構。AI 可能用 parent_id 自關聯(Adjacency List),這在查詢「某篇文章的所有留言樹」時效能不佳。如果巢狀深度固定(最多兩層),用 comment_id 和 reply_to_id 兩個欄位可能更直觀。
文章狀態。AI 可能用 BOOLEAN published,但實際上通常需要 draft、review、published、archived 多種狀態。
第三步:要求 AI 加上你發現的缺漏。
把上面的 Schema 修改:
- 文章狀態改成 ENUM('draft','review','published','archived')
- 加上 slug 欄位(VARCHAR(200), UNIQUE)給文章 URL 用
- 加上 published_at 欄位(可以是未來時間,用於排程發布)
- 留言加上 is_approved 欄位(預設 false,需要審核)
- 產生所有需要的索引
- 產生 RLS 政策:作者只能編輯自己的文章
第四步:安全檢查。把最終的 Schema 再貼一次給 AI:
請從安全角度審查以下 Schema:
- 哪些欄位是 PII?
- 有沒有缺少約束的地方?
- 有沒有 SQL Injection 風險的設計?
- 密碼儲存方式是否安全?
[貼上 Schema]
敏感欄位處理
AI 產生的 Schema 不會主動考慮敏感資料的處理。你需要自己辨識哪些欄位包含個人資料或敏感資訊,並做對應的處理。
需要加密儲存的欄位
身分證字號。如果你的系統必須儲存(例如金融業 KYC),用 AES-256-GCM 加密,加密金鑰存在 Key Management Service(例如 AWS KMS、GCP Cloud KMS),不要存在程式碼或環境變數。存加密後的值和一個不可逆的 hash(用於查詢比對)。
信用卡號碼。除非你是 PCI DSS Level 1 認證的服務商,否則不要存完整卡號。台灣的支付服務(綠界 ECPay、藍新 NewebPay、TapPay)都提供代碼化(tokenization),你只需要存 token。
密碼。用 bcrypt(work factor 12+)或 Argon2id 做 hash,不是加密。AI 有時候會建議用 SHA-256 或 MD5,這對密碼儲存來說不夠安全——這些是摘要算法,不是密碼 hash 算法,沒有鹽值(salt)和計算成本控制。
PII 欄位標記與存取控制
在 Schema 中標記 PII 欄位,方便後續做存取控制和稽核:
COMMENT ON COLUMN users.email IS 'PII - 聯絡用,需要存取控制';
COMMENT ON COLUMN users.phone IS 'PII - 驗證用,API 回傳時遮罩為 09xx-xxx-123';
COMMENT ON COLUMN users.national_id IS 'PII-Sensitive - AES-256-GCM 加密儲存';
COMMENT ON COLUMN users.birth_date IS 'PII - 年齡驗證用,報表中只顯示年齡區間';
PostgreSQL 的 Row Level Security (RLS) 可以讓不同角色只能存取自己權限範圍內的資料:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY orders_user_policy ON orders
FOR SELECT USING (user_id = current_setting('app.current_user_id')::uuid);
常見錯誤
用免費版 AI 工具分析正式環境的資料。你的 Schema 可能包含商業邏輯(從表和欄位的命名就能推斷出商業模式),把這些貼到免費版 ChatGPT 可能會被用於訓練。如果需要 AI 幫忙分析,用 API 版本或 Enterprise 版本,確認資料不會被用於訓練。
完全信任 AI 的索引建議而不做 EXPLAIN 驗證。AI 建議的索引不一定適合你的查詢模式。建好索引後,用 EXPLAIN ANALYZE 確認查詢確實有使用到索引。
在 migration 中直接修改正式資料庫。永遠要有 staging 環境,用相同結構和資料量的資料庫先測試。ORM 工具(例如 Prisma、Sequelize、Django ORM)的 migration 也是一樣,AI 產生的 migration 檔案在執行前要人工審查。
安全考量
不要把正式環境的查詢日誌或 slow query log 直接貼進 AI 工具。這些日誌可能包含實際的查詢參數,例如使用者的 email、搜尋關鍵字、或 API token。如果你需要 AI 幫忙分析查詢效能,用 EXPLAIN 輸出(不含實際資料)或把參數替換成假值。
AI 產生的 Schema 不會設定資料庫層級的存取控制。在 PostgreSQL 中,建議為不同的應用角色建立不同的資料庫使用者,每個使用者只授予需要的權限(SELECT、INSERT、UPDATE,不給 DROP、TRUNCATE)。
資料庫備份的安全。AI 可能建議用 pg_dump 產生備份,但不會提醒你:備份檔案包含所有敏感資料,需要加密儲存;備份檔案的存取權限要限制;跨境傳輸備份檔案要注意個資法的跨境傳輸規範。
工具比較
| 工具 | Schema 設計能力 | 適合情境 | 隱私考量 |
|---|---|---|---|
| ChatGPT (GPT-4o) | 好,支援多種資料庫語法 | 快速原型、學習 | 免費版資料可能用於訓練 |
| Claude | 好,長 Schema 處理穩定 | 既有 Schema 審查、長文分析 | API 版本不用於訓練 |
| GitHub Copilot | 中等,適合行內補完 | IDE 中寫 migration | 程式碼可能上傳 |
| dbdiagram.io + AI | 專門做 Schema 視覺化 | ER Diagram 產生 | 資料存在第三方伺服器 |
| Prisma AI | 專門做 ORM Schema | Prisma 使用者 | 整合在開發流程中 |
常見問題
AI 產生的 Schema 可以直接用在正式環境嗎?
不建議直接用。AI 產生的 Schema 可以作為起點,但上線前需要審查:正規化程度是否適合你的查詢模式、索引設計是否對應實際的 SQL 查詢、資料型別精確性、敏感欄位處理、約束和預設值。特別是索引和效能相關的設計,AI 通常考慮不周。建議流程是 AI 產生 → 人工審查 → staging 測試 → 正式環境。
用什麼 AI 工具設計資料庫比較好?
Claude 和 ChatGPT 在 Schema 設計上能力相近。關鍵是 Prompt 要明確指定資料庫類型(PostgreSQL 和 MySQL 的語法有差異)、正規化程度、需要的約束和索引。如果是既有專案,把現有 Schema 和常見的查詢一起提供給 AI,可以得到更精確的索引建議。如果處理的是內部系統的 Schema,建議用 API 版本而非免費的 web 版本。
AI 產生的 migration 會不會搞壞正式資料庫?
有可能。特別是在大表上做結構變更(加欄位、加索引、改資料型別)時,AI 產生的 migration 經常忽略鎖表問題。安全做法:永遠先在資料量相同的測試資料庫執行,測量執行時間和鎖表影響。確保每個 migration 都有 rollback。大表的變更分成多個步驟。在 PostgreSQL 使用 CREATE INDEX CONCURRENTLY 避免鎖表。
AI 可以幫忙做查詢效能調校嗎?
可以分析 EXPLAIN 輸出和建議索引,但 AI 不知道你的實際查詢頻率和資料分佈。Slow query log 的分析結合 AI 建議會比單純讓 AI 看 Schema 有用。提供 EXPLAIN 輸出時,記得把查詢中的真實資料替換成假值,特別是使用者的個人資訊。
如何處理台灣個資法要求的資料欄位?
個資法要求蒐集個人資料要有明確目的、告知當事人、取得同意。在 Schema 層面,建議:用 COMMENT 標記 PII 欄位;設定 Row Level Security 限制存取;記錄存取日誌(audit trail,可以用獨立的 audit_logs 表);資料刪除請求需要能真正刪除(硬刪除),所以用 deleted_at 軟刪除的系統要額外實作硬刪除的流程;跨境儲存(例如使用 AWS 東京 region)要注意個資法的跨境傳輸條件。
ORM 的 Schema 定義可以用 AI 產生嗎?
可以。用 Prisma、Sequelize、Django ORM、TypeORM 的格式讓 AI 產生 Schema 定義也是常見做法。好處是 ORM 會自動處理一些細節(例如 Prisma 會自動幫關聯欄位加索引),壞處是 AI 可能不了解特定 ORM 的慣例(例如 Django 的 ForeignKey 預設行為)。建議在 Prompt 中指定 ORM 的版本和你慣用的設定。
延伸閱讀
- AI 後端開發:Node.js/Python API 的安全開發指南(ai-backend-development)
- 用 AI 寫自動化腳本的安全指南(ai-automation-scripts)
- AI 生成的程式碼要怎麼審查?安全檢查清單(ai-generated-code-audit)