数据类型是数据库表设计的基石,选择正确的数据类型直接影响存储空间、查询性能和数据完整性。
一、数值类型
1. 整数类型
| 类型 | 字节 | 有符号范围 | 无符号范围 | 说明 |
|---|---|---|---|---|
TINYINT |
1 | -128 ~ 127 | 0 ~ 255 | 状态、标志位 |
SMALLINT |
2 | -32768 ~ 32767 | 0 ~ 65535 | 小范围数值 |
MEDIUMINT |
3 | -8388608 ~ 8388607 | 0 ~ 16777215 | 中等范围 |
INT |
4 | -21亿 ~ 21亿 | 0 ~ 42亿 | 通用整数 |
BIGINT |
8 | -922亿亿 ~ 922亿亿 | 0 ~ 1844亿亿 | 大数值(如时间戳、ID) |
使用建议
-- 状态字段:TINYINT
status TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-正常'
-- 年龄:TINYINT UNSIGNED
age TINYINT UNSIGNED DEFAULT 0
-- 普通ID:INT UNSIGNED
id INT UNSIGNED AUTO_INCREMENT
-- 大数据量:BIGINT UNSIGNED
user_id BIGINT UNSIGNED NOT NULL
二、小数类型
1. 浮点数(FLOAT / DOUBLE)
-- 近似值,会有精度误差
FLOAT -- 4字节,单精度
DOUBLE -- 8字节,双精度
-- 浮点数不精确
SELECT 0.1 + 0.2; -- 0.30000000000000004(可能有误差)
2. 定点数(DECIMAL)
DECIMAL(M, D) -- M:总位数,D:小数位数
DECIMAL(10, 2) -- 总共10位,其中2位小数,范围 -99999999.99 ~ 99999999.99
使用建议
-- 金额必须用 DECIMAL
price DECIMAL(10, 2) NOT NULL DEFAULT 0.00
-- 不要用 FLOAT 存钱
price FLOAT -- 会丢失精度
-- 不要用 DOUBLE 存钱
price DOUBLE -- 同样有精度问题
三、字符串类型
1. 定长字符串(CHAR)
CHAR(N) -- N:0~255 个字符
-
固定长度,不够用空格填充
-
适合长度固定的字段
-- 适合用 CHAR
gender CHAR(1) -- 'M' / 'F'
status CHAR(1) -- '0' / '1'
id_card CHAR(18) -- 身份证号
2. 变长字符串(VARCHAR)
VARCHAR(N) -- N:0~65535 个字符
-
可变长度,只占用实际长度 + 1/2 字节
-
适合长度不固定的字段
-- 适合用 VARCHAR
username VARCHAR(50)
email VARCHAR(100)
address VARCHAR(255)
CHAR vs VARCHAR 选择
| 场景 | 推荐 | 原因 |
|---|---|---|
| 长度固定 | CHAR |
效率更高 |
| 长度变化大 | VARCHAR |
节省空间 |
| 长度 > 255 | VARCHAR / TEXT |
CHAR 不支持 > 255 |
| 频繁更新 | CHAR |
定长不会引起页分裂 |
-- 示例:性别用 CHAR,用户名用 VARCHAR
CREATE TABLE users (
gender CHAR(1) NOT NULL,
username VARCHAR(50) NOT NULL
);
3. 大文本(TEXT)
| 类型 | 最大长度 | 说明 |
|---|---|---|
TINYTEXT |
255 | 极少使用 |
TEXT |
65535 (约64KB) | 常用 |
MEDIUMTEXT |
1677万 (约16MB) | 大文本 |
LONGTEXT |
42亿 (约4GB) | 超大文本 |
注意
-
TEXT 不能有默认值
-
TEXT 查询时可能产生临时表,影响性能
-
尽量用 VARCHAR 替代 TEXT
-- 错误:TEXT 不能设置默认值
content TEXT DEFAULT '' -- 报错-- 正确
content TEXT
四、二进制类型
| 类型 | 最大长度 | 说明 |
|---|---|---|
BINARY |
255 | 定长二进制 |
VARBINARY |
65535 | 变长二进制 |
BLOB |
65535 | 二进制大对象 |
MEDIUMBLOB |
1677万 | 中等二进制 |
LONGBLOB |
42亿 | 超大二进制 |
-- 存储图片、文件等
avatar MEDIUMBLOB
五、日期时间类型
| 类型 | 格式 | 范围 | 说明 |
|---|---|---|---|
DATE |
YYYY-MM-DD | 1000-01-01 ~ 9999-12-31 | 日期 |
TIME |
HH:MM:SS | -838:59:59 ~ 838:59:59 | 时间 |
DATETIME |
YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 | 日期+时间 |
TIMESTAMP |
YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 | Unix 时间戳 |
YEAR |
YYYY | 1901 ~ 2155 | 年份 |
TIMESTAMP vs DATETIME
| 对比 | TIMESTAMP |
DATETIME |
|---|---|---|
| 存储空间 | 4字节 | 8字节 |
| 范围 | 1970-2038 | 1000-9999 |
| 时区影响 | 自动转换 | 不转换 |
| 自动更新 | 支持 | 不支持 |
使用建议
-- 创建时间:用 DATETIME 或 TIMESTAMP
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-- 更新时间:用 TIMESTAMP(支持自动更新)
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-- 只需要日期:用 DATE
birthday DATE
-- 2038年问题:TIMESTAMP 在 2038 年溢出
expire_time TIMESTAMP -- 2038-01-19 之后会出问题
expire_time DATETIME -- 无此问题
六、JSON 类型(MySQL 5.7+)
-- 创建 JSON 列
CREATE TABLE products (
id INT PRIMARY KEY,
attributes JSON
);
-- 插入 JSON 数据
INSERT INTO products VALUES (1, '{"color": "red", "size": "L"}');
-- 查询 JSON 字段
SELECT JSON_EXTRACT(attributes, '$.color') FROM products; -- "red"
SELECT attributes->>'$.color' FROM products; -- red
-- JSON 函数
SELECT JSON_KEYS(attributes) FROM products; -- ["color", "size"]
说明:
-
整数类型选最小够用的 :
TINYINT→SMALLINT→INT→BIGINT -
金额必须用
DECIMAL,不能用浮点数 -
定长用
CHAR,变长用VARCHAR -
时间推荐
DATETIME,TIMESTAMP有 2038 年问题 -
大文本用
TEXT,但尽量用VARCHAR替代 -
JSON 类型适合灵活、非结构化的数据