DEFAULT 子句完整規則與實戰避坑
MySQL DEFAULT 預設值支援常數、部份函數、NULL,但不支援任意運算式 (8.0.13 起支援函數運算式,但有限制)。以下為各型別支援情況總表。
各資料型別預設值支援對照表
| 資料型別 | 支援常數 | 支援函數 | 典型範例 | 不支援/注意事項 |
| 整數 (TINYINT/SMALLINT/MEDIUMINT/INT/BIGINT) | ✅ | ❌ | DEFAULT 0, DEFAULT 100 | 不可用 DEFAULT (1+1) (8.0 前) |
| 浮點/定點 (FLOAT/DOUBLE/DECIMAL/NUMERIC) | ✅ | ❌ | DEFAULT 0.00, DEFAULT 99.99 | 字串常數需引號 DEFAULT '0.00' |
| 字串 (CHAR/VARCHAR/TEXT/BLOB) | ✅ | ❌ | DEFAULT '', DEFAULT 'unknown' | TEXT/BLOB 8.0 前不支援 DEFAULT |
| 日期/時間 (DATE/TIME/DATETIME) | ✅ (字串) | ❌ (8.0 前) | DEFAULT '2024-01-01', DEFAULT '12:00:00' | 不支援 NOW()/CURDATE()/CURTIME() |
| TIMESTAMP | ✅ | ✅ 特例 | DEFAULT CURRENT_TIMESTAMP, DEFAULT 0 | 首個 TIMESTAMP 欄位預設即為 CURRENT_TIMESTAMP (可關閉 explicit_defaults_for_timestamp) |
| YEAR | ✅ | ❌ | DEFAULT 2024 | |
| ENUM/SET | ✅ | ❌ | DEFAULT 'value1' | 需為列表內合法值 |
| JSON | ✅ (8.0+) | ❌ | DEFAULT '{}', DEFAULT '[]' | 需合法 JSON 文本 |
關鍵限制與特例詳細說明
- DATETIME/DATE/TIME 不支援 NOW()/CURRENT_TIMESTAMP (MySQL 5.6/5.7)。
解決:改用 TIMESTAMP 型別,或應用層寫入,或 8.0.13+ 使用 DEFAULT (CURRENT_TIMESTAMP) (需 explicit_defaults_for_timestamp=OFF)。
- TIMESTAMP 首欄位自動特性:
建表時第一個 TIMESTAMP 欄位若無顯式 DEFAULT,隱含 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。
關閉:SET GLOBAL explicit_defaults_for_timestamp = ON; (8.0 預設 ON)。
- NOT NULL + 無 DEFAULT:嚴格模式 (
STRICT_TRANS_TABLES) 下插入不給值報錯;非嚴格模式用型別「零值」 (0、''、'0000-00-00')。建議永遠顯式指定 DEFAULT。
- BLOB/TEXT 預設值:5.7 前不支援;8.0 支援
DEFAULT 'text'。
實戰建表範例
CREATE TABLE demo_defaults (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- 整數預設
status TINYINT NOT NULL DEFAULT 1,
-- 字串預設
source VARCHAR(20) NOT NULL DEFAULT 'web',
-- 定點數預設 (價格)
price DECIMAL(10,2) NOT NULL DEFAULT '0.00',
-- 時間戳:建立時間自動填充,更新時間手動維護
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
-- 日期預設 (需字串常數)
expire_date DATE NOT NULL DEFAULT '2099-12-31',
-- JSON 預設空物件
meta JSON NOT NULL DEFAULT '{}'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
從 SQL Server / Oracle 遷移注意
| 原系統寫法 | MySQL 相容寫法 | 說明 |
DEFAULT (GETDATE()) | TIMESTAMP DEFAULT CURRENT_TIMESTAMP | 改用 TIMESTAMP 型別 |
DEFAULT ('') (INT 欄位) | DEFAULT 0 | 型別必須匹配 |
DEFAULT (NULL) + NOT NULL | 移除 NOT NULL 或給實際預設值 | 邏輯衝突 |