默认值仅在insert新行时生效,用于自动填充未显式赋值的字段;不作用于update或已有数据,且null本身不是默认值,需显式定义default null才填null。

MySQL 字段的默认值,就是当你插入一条新记录、但没给这个字段显式赋值时,数据库自动填进去的那个值。
它不是“兜底容错”,而是明确的预设行为;不写值 ≠ 留空,而是按 DEFAULT 填。
默认值什么时候生效?只对 INSERT 新行起作用
默认值不会修改已有数据,也不会影响 UPDATE(除非你显式写 UPDATE ... SET col = DEFAULT)。它只在以下场景触发:
- 执行
INSERT INTO t(col1, col2) VALUES('a', 'b'),而表定义里col3有DEFAULT 0→ 自动补0 - 执行
INSERT INTO t() VALUES()(空列列表),所有带 DEFAULT 的字段都会被填充 - 执行
INSERT INTO t SET col1='x',其他未提字段若含 DEFAULT,则按默认值填
注意:NULL 不是默认值 —— 如果字段允许 NULL 且没设 DEFAULT,不填就是 NULL;如果设了 DEFAULT NULL,那才是主动填 NULL。
哪些类型能设默认值?时间函数和字符串要特别小心
MySQL 对默认值支持有限制,尤其老版本(
-
DATETIME/TIMESTAMP:可用CURRENT_TIMESTAMP或NOW(),但CURDATE()、CURTIME()在部分版本不被允许作为 DEFAULT(会报错Invalid default value) -
TEXT/BLOB:**一律不能设默认值**(MySQL 8.0.19+ 对LONGTEXT有例外,但不推荐依赖) - 字符串必须用单引号:写
DEFAULT 'active'✅,写DEFAULT active❌(会被当列名或函数) - 数值不用引号:
DEFAULT 1✅,DEFAULT '1'❌(可能隐式转类型,尤其配合TINYINT时易出错)
CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT, status TINYINT NOT NULL DEFAULT 1, remark VARCHAR(255) DEFAULT '', created_at DATETIME DEFAULT CURRENT_TIMESTAMP );
已有表怎么改默认值?语法因 MySQL 版本而异
MySQL 5.7 和 8.0+ 的语法不兼容,别抄错:
- MySQL 8.0.13+ 推荐用:
ALTER TABLE t ALTER COLUMN c SET DEFAULT 'val' - MySQL 5.7 或兼容写法(本质是重定义字段):
ALTER TABLE t MODIFY COLUMN c VARCHAR(20) DEFAULT 'val' - 删默认值也分版本:
DROP DEFAULT是 8.0+ 语法;5.7 只能用MODIFY把 DEFAULT 去掉
验证是否生效?别信文档,直接查:
SHOW CREATE TABLE orders;
输出里能看到 status TINYINT DEFAULT '1' 这类定义,才真正落地了。
为什么字段设了 NOT NULL 还要配 DEFAULT?
因为 NOT NULL 只拒绝 NULL,不提供替代值。没 DEFAULT 时,只要 INSERT 漏写该字段,就直接报错:
ERROR 1364 (HY000): Field 'status' doesn't have a default value
所以生产环境强烈建议:所有 NOT NULL 字段,都配上语义合理的 DEFAULT(比如状态字段用 1,金额用 0.00,时间用 CURRENT_TIMESTAMP)。这不是偷懒,是堵住客户端漏传字段的漏洞。
最后提醒一句:DEFAULT 不是魔法,它不校验业务逻辑,也不阻止你手动插个非法值(比如给状态字段插个 999)。该加 CHECK 约束、该建枚举注释、该在应用层做校验,一样不能少。










