大家好,我是 lazy,一名双非大二科班学生。上一篇我们讲了 DDL 的建库建表基础操作,这篇继续深入——专门讲 MySQL 数据类型的完整解析,包括数值、字符串、日期三大类,每一类都附上选型建议和避坑指南,跟着学完直接上手不踩坑。


一、数值类型

1. 整数类型

MySQL 提供了五种整数类型,按存储空间从小到大依次为:

类型 字节数 有符号范围 无符号范围
TINYINT 1 -128 ~ 127 0 ~ 255
SMALLINT 2 -32768 ~ 32767 0 ~ 65535
MEDIUMINT 3 -8388608 ~ 8388607 0 ~ 16777215
INT 4 -2^31 ~ 2^31-1 0 ~ 42 亿
BIGINT 8 -2^63 ~ 2^63-1 0 ~ 1844 亿亿

选型建议:

业务场景 推荐类型
状态码、年龄、性别、枚举值 TINYINT
省份 ID、分类 ID、小范围计数 SMALLINT
中等规模自增 ID(百万级以内) MEDIUMINT
通用自增主键、用户 ID、商品 ID INT(最常用)
超大自增 ID、分布式 ID、毫秒时间戳 BIGINT

💡 自增主键选型口诀:中小型项目用 INT UNSIGNED(上限 42 亿),大型/分布式项目用 BIGINT UNSIGNED(永无溢出风险)。

⚠️ MySQL 8.0 之后,INT(11) 这类显示宽度写法已不再生效,仅为历史兼容,不影响实际存储范围,新项目直接写 INT 即可。


2. 浮点类型(FLOAT / DOUBLE)
类型 字节数 精度 问题
FLOAT 4 约 6~7 位有效数字 精度低,存在舍入误差
DOUBLE 8 约 15~16 位有效数字 精度更高,但仍有浮点误差

⚠️ 致命坑:绝对不能用浮点数存金额! 浮点数是近似值存储,比如 0.1 + 0.2 在计算机中实际结果是 0.30000000000000004,金额、财务数据出现这种误差是灾难性的。


3. 定点类型(DECIMAL)

DECIMAL 是精确存储,完全没有浮点误差,是金额计算的唯一正确选择。

语法: DECIMAL(M, D)

  • M:总有效数字长度(1~65,默认 10)
  • D:小数点后的位数(0~30,默认 0)
-- 示例:最多 10 位数字,其中 2 位小数
price DECIMAL(10, 2)   -- 范围:-99999999.99 ~ 99999999.99

-- 成绩示例:总长度4,小数位数1
score DOUBLE(4, 1)

选型建议:

场景 推荐类型
金额、价格、财务数据 DECIMAL(必须)
科学计算、非精确统计 DOUBLE
性能优先、对精度要求极低 FLOAT(不推荐)

💡 DECIMAL 比 DOUBLE 稍慢,但现代数据库中性能差距可忽略不计,精度永远优先。


二、字符串类型

完整类型一览
类型 大小 描述
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TINYTEXT 0-255 bytes 短文本字符串
TEXT 0-65535 bytes 长文本数据
MEDIUMTEXT 0-16777215 bytes 中等长度文本数据
LONGTEXT 0-4294967295 bytes 极大文本数据
TINYBLOB 0-255 bytes 小二进制数据
BLOB 0-65535 bytes 二进制长文本数据
MEDIUMBLOB 0-16777215 bytes 中等二进制数据
LONGBLOB 0-4294967295 bytes 极大二进制数据

1. 最常用:CHAR vs VARCHAR
特性 CHAR(n) VARCHAR(n)
存储方式 固定占用 n 字节,不足用空格填充 按实际长度存储,额外 1-2 字节记录长度
性能 读写更快,无额外长度计算 稍慢,需计算实际长度
空间利用率 短字符串浪费空间 按需分配,利用率高
适用场景 固定长度字段:手机号、状态码、性别

不固定长度字段:用户名、昵称、地址

-- CHAR 适合固定长度
phone    CHAR(11)     COMMENT '手机号',
gender   CHAR(1)      COMMENT '性别',

-- VARCHAR 适合可变长度
username VARCHAR(50)  COMMENT '用户名',
email    VARCHAR(100) COMMENT '邮箱',
address  VARCHAR(255) COMMENT '地址'

⚠️ utf8mb4 字符集下,VARCHAR(n) 中 n 是字符数,1 个字符占 4 字节,因此实际最大 n ≈ 16383,建表时按需设置,不要无脑写 VARCHAR(255)


2. TEXT 系列 vs BLOB 系列
类型组 核心区别 适用场景
TEXT 系列 存储文本,按字符集编码解析 文章内容、评论、日志、富文本
BLOB 系列 存储二进制,原样存储不做编码解析 图片、文件、音频、加密数据

⚠️ TEXT/BLOB 不能设置默认值,也不建议在这类字段上做排序、分组、关联查询,性能极差。大字段建议单独拆表存储。

💡 实际项目中,图片、视频等二进制文件不推荐直接存数据库,应存文件服务器或 OSS(对象存储),数据库只存文件路径,性能和可维护性都更好。


3. 选型速查
业务场景 推荐类型
固定长度短字段(手机号、状态码) CHAR
可变长度短/中字段(用户名、邮箱) VARCHAR
短文本(≤255 字符,简介备注) TINYTEXT
普通长文本(≤64KB,文章评论) TEXT
中等长文本(≤16MB,富文本文档) MEDIUMTEXT
超大文本(≤4GB,电子书日志) LONGTEXT
小二进制文件(≤255B) TINYBLOB
普通二进制文件(≤64KB) BLOB
中等二进制文件(≤16MB,音频图片) MEDIUMBLOB
超大二进制文件(≤4GB,视频) LONGBLOB

三、日期类型

完整类型一览
类型 字节 范围 格式 描述
DATE 3 1000-01-01 ~ 9999-12-31 YYYY-MM-DD 日期值
TIME 3 -838:59:59 ~ 838:59:59 HH:MM:SS 时间值或持续时间
YEAR 1 1901 ~ 2155 YYYY 年份值
DATETIME 8 1000-01-01 ~ 9999-12-31 YYYY-MM-DD HH:MM:SS 日期时间值
TIMESTAMP 4 1970-01-01 ~ 2038-01-19 YYYY-MM-DD HH:MM:SS 时间戳,与时区相关

1. 最常用:DATETIME vs TIMESTAMP
特性 DATETIME TIMESTAMP
存储范围 1000-01-01 ~ 9999-12-31 1970-01-01 ~ 2038-01-19(有上限)
时区依赖 与时区无关,存储原始时间 自动转换为服务器时区存储
存储空间 8 字节 4 字节(更省空间)
自动赋值 需手动设置 可设置 DEFAULT CURRENT_TIMESTAMP 自动更新
适用场景 历史数据、跨时区系统 日志时间、创建/更新时间

⚠️ TIMESTAMP 的 2038 年问题: 32 位时间戳上限是 2038-01-19 03:14:07,超过会溢出报错。现代系统推荐优先使用 DATETIME(6) 支持微秒,彻底规避这个问题。


2. 推荐写法:自动更新时间
CREATE TABLE orders (
  id          INT           COMMENT '订单ID',
  user_id     INT           COMMENT '用户ID',
  amount      DECIMAL(10,2) COMMENT '金额',
  -- 创建时自动赋值,更新时自动刷新
  create_time DATETIME DEFAULT CURRENT_TIMESTAMP        COMMENT '创建时间',
  update_time DATETIME DEFAULT CURRENT_TIMESTAMP
              ON UPDATE CURRENT_TIMESTAMP               COMMENT '更新时间'
) COMMENT '订单表';

💡 MySQL 8.0+ 支持 DATETIME 也使用 ON UPDATE CURRENT_TIMESTAMP,不再局限于 TIMESTAMP,新项目统一用 DATETIME 即可。


3. 选型速查
业务需求 推荐类型 示例
仅存日期 DATE birthday DATE
仅存时间/时长 TIME duration TIME
通用创建/更新时间 DATETIME(6) create_time DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
日志/埋点时间(毫秒级) DATETIME(3) log_time DATETIME(3)
跨时区系统时间 DATETIME(存 UTC) utc_time DATETIME
仅存年份(不推荐) YEAR birth_year YEAR

⚠️ YEAR 类型只支持 1901~2155,且 2 位输入会自动补全('99' → 1999),容易产生歧义,建议直接用 DATEDATETIME 替代。


四、数据类型选型总速查

业务场景 推荐类型
状态/枚举/年龄 TINYINT
普通自增主键 INT
超大自增 ID/分布式 ID BIGINT
金额/价格/财务 DECIMAL(M,D)
科学计算/非精确统计 DOUBLE
固定长度字符串 CHAR
可变长度字符串 VARCHAR
长文本内容 TEXT
二进制文件路径(文件本身存 OSS) VARCHAR
仅存日期 DATE
通用时间字段 DATETIME(6)
自动更新时间 DATETIME + ON UPDATE

总结

数据类型的选择看起来细碎,但它直接影响存储空间、查询性能和数据准确性。记住几条核心原则:

  • 金额必须用 DECIMAL,浮点数会出现精度误差
  • 主键根据数据规模选 INT BIGINT
  • 字符串优先用 CHAR/VARCHAR,大文本才考虑 TEXT
  • 时间字段推荐 DATETIME(6),规避 TIMESTAMP 的 2038 问题
  • 文件不要存数据库,存路径就够了

下一篇会继续讲 DDL 表的修改与删除操作,敬请期待。如果这篇对你有帮助,点个赞再走吧~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐