原创

聊聊表设计时是否有必要给字段设置默认值

温馨提示:
本文最后更新于 2025年05月22日,已超过 15 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

在系统表设计过程中,一般我们都建议给字段设置非空并设置默认值,实际过程中,设置字段为空&无默认值是一种常见偷懒情况,且在设计及初始编码过程中非常方便,于是对字段是否为空及是否需要设置默认值经常会存在一定争议,今天我们就针对此问题进行简单探讨。

建议

  • 对字符串类字段设置非空&默认空字符串''而不是NULL
  • 对数字类字段设置非空&默认0而不是NULL
  • 对时间类字段设置非空&默认当前时间或系统最小时间如'1970-01-01'保证数据一致

分析

NULL与NOT NULL的本质差异

NULL的语义特殊性

NULL表示"未知"或"不存在",区别于空字符串/0等实际值。在SQL标准中,NULL=NULL的运算结果为UNKNOWN而非TRUE,这种值逻辑直接影响查询结果(如WHERE条件过滤)。

存储与索引代价

  • NULL值需要额外1字节的标记位存储,InnoDB中可变长度字段的NULL不占空间但需维护NULL标志位
  • B-Tree索引不存储NULL值,导致WHERE col IS NULL需全表扫描,且=、!=、in、not in等查询不到值;而NOT NULL字段配合默认值可建立全覆盖索引
示例
id name status
1 test NULL
2 test2
3 test3 1
4 test4
SELECT * FROM t_user WHERE `status` = NULL;
SELECT * FROM t_user WHERE `status` != NULL;
查询结果

=或!=查询不到任何数据

id name status
SELECT * FROM t_user WHERE `status` IS NULL;
查询结果

IS NULL 查询到值为NULL的数据而空字符串不包含在内

id name status
1 test NULL
EXPLAIN SELECT * FROM t_user WHERE `status` IS NULL;
解析结果

IS NULL 使用索引查询

id select_type table partitions type possible_keys key key_length ref rows filltered Extra
1 SIMPLE t_user ref idx_status idx_status 303 const 1 100.00 Using index condition
EXPLAIN SELECT * FROM t_user WHERE `status` = '';

='' 使用索引查询

解析结果
id select_type table partitions type possible_keys key key_length ref rows filltered Extra
1 SIMPLE t_user ref idx_status idx_status 303 const 2 100.00 Using index condition
EXPLAIN SELECT * FROM t_user WHERE `status` = NULL;

= NULL 查询不到任何数据

解析结果
id select_type table partitions type possible_keys key key_length ref rows filltered Extra
1 SIMPLE no matching row in const table
SELECT count(`status`) FROM t_user;

count统计缺失NULL数据

解析结果
count(status)
3
正文到此结束
本文目录