error 1101 根本原因是mysql严格模式下禁止blob/text/geometry/json列设默认值,源于行外存储设计与性能考量;8.0.13+虽支持字面量默认值,但需dynamic行格式且版本达标,否则须删default子句或改用null。

MySQL 5.7/8.0 报 ERROR 1101 的根本原因
不是语法写错了,也不是你漏写了引号——ERROR 1101 (42000): BLOB, TEXT, GEOMETRY or JSON column 'x' can't have a default value 是 MySQL 在严格模式(STRICT_TRANS_TABLES 等)下主动拒绝建表语句的硬性限制。它源于存储引擎层的设计取舍:InnoDB 对 BLOB/TEXT 类型采用“行外存储”(off-page storage),默认值无法像普通字段那样直接固化在表元数据或聚集索引中;同时,大字段默认值会显著放大 INSERT 时的内存开销和日志体积,尤其在批量导入场景下易触发 max_allowed_packet 或临时表溢出。
MySQL 8.0.13+ 其实已部分放开限制
别被旧文档带偏——从 MySQL 8.0.13 开始,TEXT 和 BLOB 列**支持常量默认值**(如 DEFAULT ''、DEFAULT 'hello'),但仅限于字面量字符串,不支持函数或表达式(如 DEFAULT CURRENT_TIMESTAMP 不行)。不过这个特性默认不生效,需满足两个条件:
- MySQL 版本 ≥ 8.0.13
- 表使用
DYNAMIC或COMPRESSED行格式(SHOW CREATE TABLE t可查)
验证方式:CREATE TABLE t (c TEXT DEFAULT ''); 在 8.0.13+ + DYNAMIC 行格式下可成功;若仍报错,大概率是行格式不对或版本不够。
为什么 NOT NULL + TEXT 也报错?
TEXT 字段声明 NOT NULL 会隐式触发默认值检查:MySQL 要求所有 NOT NULL 列必须有明确的可插入值,而老版本不支持 TEXT 默认值,就导致逻辑断路。所以错误信息常是 TEXT column 'x' can't be NOT NULL,本质还是默认值能力缺失。解决路径只有两条:
- 去掉
NOT NULL,接受NULL(最常见且推荐) - 升级到 8.0.13+ 并显式加
DEFAULT '' NOT NULL(需确认行格式)
注意:DEFAULT NULL 本身不合法,TEXT 列允许 NULL 是靠省略 DEFAULT 子句实现的,不是靠写 DEFAULT NULL。
应用层该怎么做才不踩坑
别指望 DDL 解决语义问题。真实项目里,99% 的“空文本”需求其实是业务语义(比如“用户没填简介”),不是数据库约束问题。正确做法是:
- 建表时写成
content TEXT NULL(显式声明,避免歧义) - ORM 插入时统一用
NULL或空字符串(如 Laravel 的$model->content = '';) - 查询时用
IFNULL(content, '')或应用层判空,而非依赖 DB 默认值兜底 - 如果真需要 JSON 结构化默认值,改用
JSON DEFAULT '{}';(MySQL 8.0.19+ 原生支持,比 TEXT 更安全)
最易被忽略的一点:mysqldump 导出的 SQL 文件可能保留旧版 DEFAULT 定义,导入到新实例时直接炸——别急着关 strict mode,先用 sed 批量删掉 TEXT 后的 DEFAULT 子句更稳妥。











