省略列与显式写空值的区别
插入时「不写这一列」和「写一个空值」是两件事:前者让数据库套用列默认值,后者把空值真的存进去。多数框架把未赋值的字段序列化成显式空值,于是精心设计的默认值被绕过,字段里塞满了空值而没有任何报错。需要强制取默认值时,两种数据库都支持在取值列表里直接写默认值关键字,更新语句的赋值处同样可用。
基本信息
| 适用平台 | MySQL 8.0 / PostgreSQL 12 及以上 |
|---|---|
| 省略列 | 应用列默认值;无默认值且不允许为空时报错 |
| 写空值 | 存入空值;不允许为空的列直接报错 |
| 默认值关键字 | 在取值列表或赋值处显式取默认值 |
| 严格模式 | MySQL 8.0 默认开启,写入空值到非空列直接报错 |
典型使用场景
- 新建记录只提供部分字段,其余交给默认值
- 数据修正:把某列改回默认值而不是写成空值
- 排查字段大面积为空值:确认是不是框架把未赋值字段序列化成了空值
- 跨版本行为核对:非严格模式下写入空值会被替换成隐式默认值
- 批量导入时保持默认值语义一致
三种写法与结果
三种写法与结果
-- 省略列:应用列默认值
INSERT INTO t (name) VALUES ('x');
-- 显式空值:列可空时存空值,覆盖默认值
INSERT INTO t (name, status) VALUES ('y', NULL);
-- 强制默认:在取值列表里直接写默认值关键字
INSERT INTO t (name, status) VALUES ('z', DEFAULT);
-- 更新语句里同样可以取默认值
UPDATE t SET status = DEFAULT WHERE id = 1;
-- 确认列的默认值与可空性
-- MySQL:SHOW CREATE TABLE t;
-- PostgreSQL:查询 information_schema.columns
-- 排查空值来源:确认应用是否把未赋值字段序列化成了空值写法与结果对照
| 写法 | 结果 | 报错条件 |
|---|---|---|
| 省略列 | 套用列默认值 | 无默认值且不允许为空 |
| 写空值 | 存入空值 | 列不允许为空 |
| 写默认值关键字 | 套用列默认值 | 该处不支持该语法时 |
| 更新为默认值 | 列恢复默认值 | 列没有默认值时写入空值 |
| 非严格模式写空值 | 被替换成隐式默认值 | 不报错,行为与严格模式不同 |
严格模式是老版本与新版本行为差异的分水岭:开的时候写入非法值直接报错,关的时候可能变成截断或隐式替换,数据静默变形。核对历史数据时先确认当时的模式设置。
排查「为什么这一列全是空值」时,先看应用层的序列化逻辑。让对象映射框架跳过未赋值字段,或者在语句里显式写默认值关键字,都比事后补数据干净。