DEFAULT关键字仅在INSERT ... VALUES中显式补全默认值,INSERT ... SELECT中不支持需用NOW()或COALESCE替代;MySQL中ON DUPLICATE KEY UPDATE须写DEFAULT(col),SQLite不支持函数型默认值。

INSERT语句中显式使用DEFAULT关键字补全字段值
当表定义了列的DEFAULT约束(比如created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP),但你在INSERT里又想明确表达“用默认值”,就得写DEFAULT——不能留空、不能写NULL(除非默认值本身就是NULL,且列允许NULL)。
常见错误是漏掉该字段,以为会自动填充;或者误写成NULL,结果存入NULL而非默认值。
-
INSERT INTO users (name, status, created_at) VALUES ('Alice', 'active', DEFAULT);—— 正确:显式触发默认逻辑 - 省略
created_at列:依赖数据库是否开启严格模式,MySQL 5.7+ 严格模式下可能报错Field 'created_at' doesn't have a default value - 写成
NULL:VALUES ('Alice', 'active', NULL)—— 若列不允许NULL则报错;若允许,则存NULL,跳过默认值逻辑
INSERT ... SELECT场景下DEFAULT不生效,需改用COALESCE或子查询
DEFAULT只在VALUES列表中合法,在INSERT ... SELECT里直接写DEFAULT会报错DEFAULT is not supported in this context(MySQL/PostgreSQL均如此)。
此时得绕开:用COALESCE模拟默认行为,或把默认值硬编码进SELECT,或拆成两步。
- PostgreSQL支持
INSERT INTO t(a,b) SELECT 'x', DEFAULT FROM ...,但MySQL完全不支持 - MySQL通用解法:
INSERT INTO users (name, status, created_at) SELECT 'Bob', 'pending', NOW();—— 把NOW()当默认值硬写 - 更灵活的做法:
SELECT COALESCE(input_time, NOW()),前提是源数据允许NULL并想 fallback 到默认值
不同数据库对DEFAULT的解析差异
语法看似一致,但底层行为可能差很远。比如DEFAULT在MySQL中可触发函数(如CURRENT_TIMESTAMP),而SQLite只支持字面量默认值(DEFAULT 42或DEFAULT 'hello'),不支持函数。
- MySQL:
DEFAULT可绑定函数,每次插入都重新求值 - PostgreSQL:
DEFAULT支持函数,也支持GENERATED ALWAYS AS列(那是另一套机制) - SQLite:
DEFAULT datetime('now')是非法的;只能写DEFAULT '2024-01-01'这类静态值 - SQL Server:用
DEFAULT关键字没问题,但更常见的是省略字段(前提是定义了DEFAULT约束)
用INSERT ... ON DUPLICATE KEY UPDATE时DEFAULT要加括号
在MySQL中,如果想在冲突更新时把某列重置为默认值,不能直接写col = DEFAULT,必须写成col = DEFAULT(col),否则会当成字面量DEFAULT字符串。
- 错误:
INSERT INTO logs (id, msg, updated_at) VALUES (1, 'err', NOW()) ON DUPLICATE KEY UPDATE updated_at = DEFAULT;→ 报错或存字符串 - 正确:
ON DUPLICATE KEY UPDATE updated_at = DEFAULT(updated_at); - 注意:
DEFAULT(col)是MySQL特有语法,PostgreSQL用EXCLUDED.col或DEFAULT上下文不同,不可混用

















