MySQL中DEFAULT只在INSERT完全省略字段或显式写DEFAULT时生效;建表时字符串需单引号、数值不加引号、时间用CURRENT_TIMESTAMP(不带括号);NOT NULL字段未设DEFAULT且启用严格模式会报错;TEXT/BLOB旧版本不支持DEFAULT;ALTER TABLE修改默认值需按版本选ALTER COLUMN SET DEFAULT或MODIFY COLUMN;删除用DROP DEFAULT;默认值不影响已有数据,仅作用于后续INSERT。

直接说结论:MySQL 中用 DEFAULT 设置默认值,只在 INSERT 时**完全省略该字段**或**显式写 DEFAULT** 才会生效;它不是“兜底填充逻辑”,更不是 ORM 层的默认赋值代理。
CREATE TABLE 时设置默认值的写法和陷阱
建表是最稳妥的时机,语法简单但细节多:
- 字符串必须加单引号:
status VARCHAR(20) DEFAULT 'active',写成DEFAULT active会报错 - 数值不用引号:
score TINYINT DEFAULT 0,DEFAULT '0'可能触发隐式类型转换 - 时间类型优先用
CURRENT_TIMESTAMP:created_at DATETIME DEFAULT CURRENT_TIMESTAMP;不能加括号,CURRENT_TIMESTAMP()是非法的 -
NOT NULL字段若没设DEFAULT,且 SQL mode 启用了STRICT_TRANS_TABLES,插入时省略该字段必报错:Field 'xxx' doesn't have a default value -
TEXT和BLOB类型在 MySQL 8.0.19 之前不支持DEFAULT(哪怕写DEFAULT ''也会被拒绝)
ALTER TABLE 修改默认值的两种语法差异
已有表加默认值,版本决定你该用哪条命令:
- MySQL 8.0.13+ 推荐用标准语法:
ALTER TABLE users ALTER COLUMN status SET DEFAULT 'inactive' - 兼容旧版本(如 5.7)必须用
MODIFY COLUMN:ALTER TABLE users MODIFY COLUMN status VARCHAR(20) DEFAULT 'inactive';注意:这会重定义整列,必须完整写出类型和约束(比如漏掉NOT NULL就可能把非空约束删了) - 想删默认值,用
DROP DEFAULT:ALTER TABLE users ALTER COLUMN email DROP DEFAULT;不要写DEFAULT NULL—— 那仍是默认值,且对NOT NULL字段直接冲突 - 执行后**不影响已有数据**,只作用于后续未显式赋值的
INSERT
INSERT 时默认值不生效的常见原因
写了 DEFAULT 却发现字段还是 NULL 或报错,大概率是这些点被忽略:
- 客户端驱动(如 JDBC、PyMySQL)把空字符串
''自动转成NULL,而字段又是NOT NULL,导致绕过默认值逻辑 - SQL mode 含
STRICT_ALL_TABLES时,即使字段允许NULL,插入NULL值也会被拒绝(而非退而使用默认值) - 误以为
UPDATE会触发默认值 —— 不会。DEFAULT仅对INSERT生效;UPDATE ... SET col = DEFAULT才强制重置为默认值 - JSON 类型字段不能设
DEFAULT '',必须用DEFAULT (JSON_OBJECT())或DEFAULT NULL
最常被忽略的一点:默认值是否生效,和字段是否允许 NULL 完全无关。一个 name VARCHAR(50) DEFAULT 'unknown' NULL 字段,插入时省略 name,填进去的就是 'unknown',不是 NULL;反过来,name VARCHAR(50)(没写 NOT NULL 也没写 DEFAULT),省略该字段的结果就是 NULL,不是空字符串。


















