MySQL 数据类型
本章将详细介绍 MySQL 支持的各种数据类型及其使用场景。
知识速查 (常用类型)
| 类型 | 示例 | 适用场景 |
|---|---|---|
| INT | INT | 整数 ID、数量 |
| DECIMAL | DECIMAL(10, 2) | 金额、精确小数 |
| VARCHAR | VARCHAR(255) | 姓名、地址、标题 |
| TEXT | TEXT | 文章内容、详细描述 |
| DATETIME | DATETIME | 创建、修改时间 |
| JSON | JSON | 半结构化配置、属性 |
| ENUM | ENUM('A', 'B') | 状态、性别 (固定值) |
数据类型概述
MySQL 支持以下几类数据类型:
- 数值类型:整数、浮点数、定点数
- 字符串类型:CHAR、VARCHAR、TEXT 等
- 日期时间类型:DATE、TIME、DATETIME、TIMESTAMP 等
- JSON 类型:JSON 数据
- 其他类型:ENUM、SET、BLOB 等
数值类型
整数类型
| 类型 | 字节 | 有符号范围 | 无符号范围 |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2 | -32,768 ~ 32,767 | 0 ~ 65,535 |
| MEDIUMINT | 3 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 |
| INT | 4 | -21亿 ~ 21亿 | 0 ~ 42亿 |
| BIGINT | 8 | -922亿亿 ~ 922亿亿 | 0 ~ 1844亿亿 |
使用示例:
CREATE TABLE numbers (
id INT AUTO_INCREMENT PRIMARY KEY,
age TINYINT UNSIGNED, -- 年龄(0-255)
score SMALLINT, -- 分数(-32768~32767)
population INT UNSIGNED, -- 人口(无符号)
view_count BIGINT UNSIGNED -- 浏览量(大数字)
);
-- 插入数据
INSERT INTO numbers (age, score, population, view_count)
VALUES (25, 98, 1400000000, 9999999999999);
整数显示宽度:
-- INT(M) 中的 M 是显示宽度,不影响存储范围
-- 配合 ZEROFILL 使用时,不足位数会用 0 填充
CREATE TABLE display_width (
id INT(6) ZEROFILL -- 如:000001
);
-- MySQL 8.0.17+ 已弃用显示宽度
浮点类型
| 类型 | 字节 | 说明 |
|---|---|---|
| FLOAT | 4 | 单精度浮点数 |
| DOUBLE | 8 | 双精度浮点数 |
CREATE TABLE floats (
id INT PRIMARY KEY,
price FLOAT, -- 单精度
rate DOUBLE, -- 双精度
precise_price FLOAT(7, 2), -- 总共 7 位,小数 2 位
precise_rate DOUBLE(15, 4) -- 总共 15 位,小数 4 位
);
-- 注意:浮点数有精度问题
INSERT INTO floats VALUES (1, 0.1, 0.1, 123.45, 1234567890.1234);
SELECT price + 0.1 FROM floats WHERE id = 1; -- 可能不是精确的 0.2
定点类型
DECIMAL 用于存储精确的小数:
CREATE TABLE decimals (
id INT PRIMARY KEY,
money DECIMAL(10, 2), -- 总共 10 位,小数 2 位
salary DECIMAL(12, 2) -- 适合存储金额
);
-- DECIMAL 存储精确值
INSERT INTO decimals VALUES (1, 12345678.90, 9999999999.99);
-- 金额计算必须用 DECIMAL
SELECT money + 0.01 FROM decimals; -- 精确计算
浮点数 vs 定点数:
| 特性 | FLOAT/DOUBLE | DECIMAL |
|---|---|---|
| 存储方式 | 二进制浮点 | 字符串存储 |
| 精度 | 近似值 | 精确值 |
| 适用场景 | 科学计算 | 金额计算 |
| 性能 | 较高 | 较低 |
BIT 类型
存储位字段:
CREATE TABLE bit_example (
id INT PRIMARY KEY,
flags BIT(8) -- 8 位
);
INSERT INTO bit_example VALUES (1, b'10101010');
-- 读取时显示为十进制或十六进制
SELECT id, flags, flags + 0 AS decimal_value, HEX(flags) AS hex_value
FROM bit_example;
字符串类型
CHAR 和 VARCHAR
| 类型 | 说明 | 最大长度 |
|---|---|---|
| CHAR(M) | 定长字符串 | 255 字符 |
| VARCHAR(M) | 变长字符串 | 65,535 字节 |
CREATE TABLE strings (
id INT PRIMARY KEY,
code CHAR(10), -- 固定 10 字符,不足补空格
name VARCHAR(50), -- 最多 50 字符
description VARCHAR(1000) -- 最多 1000 字符
);
INSERT INTO strings VALUES (1, 'ABC', '张三', '这是一段描述');
-- CHAR 适合存储固定长度的数据
-- 如:手机号、身份证号、MD5 值
CHAR vs VARCHAR:
| 特性 | CHAR | VARCHAR |
|---|---|---|
| 存储 | 定长,不足补空格 | 变长,按实际存储 |
| 最大长度 | 255 字符 | 65,535 字节 |
| 性能 | 查询较快 | 空间效率高 |
| 适用 | 固定长度数据 | 变长数据 |
TEXT 类型
| 类型 | 最大长度 |
|---|---|
| TINYTEXT | 255 字节 |
| TEXT | 65,535 字节 (64KB) |
| MEDIUMTEXT | 16MB |
| LONGTEXT | 4GB |
CREATE TABLE articles (
id INT PRIMARY KEY,
title VARCHAR(200),
summary TEXT, -- 文章摘要
content MEDIUMTEXT -- 文章内容
);
-- TEXT 类型不能有默认值
-- TEXT 类型在排序时只使用前 max_sort_length 字节
BINARY 和 VARBINARY
存储二进制字符串:
CREATE TABLE binary_data (
id INT PRIMARY KEY,
hash BINARY(32), -- 存储 MD5 哈希
uuid BINARY(16) -- 存储 UUID
);
-- 查询时使用 HEX() 函数
SELECT id, HEX(hash) AS hash_hex FROM binary_data;
BLOB 类型
存储大二进制数据:
| 类型 | 最大长度 |
|---|---|
| TINYBLOB | 255 字节 |
| BLOB | 65,535 字节 (64KB) |
| MEDIUMBLOB | 16MB |
| LONGBLOB | 4GB |
CREATE TABLE files (
id INT PRIMARY KEY,
name VARCHAR(255),
mime_type VARCHAR(100),
data 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 |
| YEAR | YYYY | 1901 ~ 2155 |
DATE 类型
CREATE TABLE dates (
id INT PRIMARY KEY,
birth_date DATE, -- 生日
hire_date DATE -- 入职日期
);
INSERT INTO dates VALUES (1, '1990-05-15', '2024-01-01');
-- 日期函数
SELECT
birth_date,
YEAR(birth_date) AS year,
MONTH(birth_date) AS month,
DAY(birth_date) AS day,
DAYOFWEEK(birth_date) AS weekday
FROM dates;
TIME 类型
CREATE TABLE times (
id INT PRIMARY KEY,
start_time TIME, -- 开始时间
duration TIME -- 持续时间
);
INSERT INTO times VALUES (1, '09:00:00', '02:30:00');
-- 时间函数
SELECT
start_time,
HOUR(start_time) AS hour,
MINUTE(start_time) AS minute,
SECOND(start_time) AS second
FROM times;
DATETIME 类型
CREATE TABLE datetimes (
id INT PRIMARY KEY,
created_at DATETIME, -- 创建时间
updated_at DATETIME -- 更新时间
);
-- 插入当前时间
INSERT INTO datetimes VALUES (1, NOW(), NOW());
-- MySQL 5.6.5+ 支持自动更新
CREATE TABLE auto_datetime (
id INT PRIMARY KEY,
name VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
TIMESTAMP 类型
CREATE TABLE timestamps (
id INT PRIMARY KEY,
event_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- TIMESTAMP 自动转换为 UTC 存储,查询时转换为当前时区
-- DATETIME 不做时区转换
DATETIME vs TIMESTAMP:
| 特性 | DATETIME | TIMESTAMP |
|---|---|---|
| 范围 | 1000-9999 年 | 1970-2038 年 |
| 存储 | 8 字节 | 4 字节 |
| 时区 | 不转换 | 自动转换 |
| 默认值 | 支持函数默认 | 支持自动更新 |
YEAR 类型
CREATE TABLE years (
id INT PRIMARY KEY,
year_value YEAR
);
INSERT INTO years VALUES (1, 2024);
-- 两位数年份的转换规则
-- 00-69 → 2000-2069
-- 70-99 → 1970-1999
INSERT INTO years VALUES (2, 24); -- 2024
INSERT INTO years VALUES (3, 99); -- 1999
JSON 类型
MySQL 5.7.8+ 支持 JSON 类型:
CREATE TABLE json_data (
id INT PRIMARY KEY,
data JSON,
config JSON
);
-- 插入 JSON 数据
INSERT INTO json_data VALUES (
1,
'{"name": "张三", "age": 25, "hobbies": ["阅读", "游泳"]}',
'{"theme": "dark", "language": "zh-CN"}'
);
-- JSON 函数
SELECT
data->>'$.name' AS name,
data->'$.age' AS age,
data->'$.hobbies[0]' AS first_hobby
FROM json_data;
-- JSON 路径表达式
-- $ 根元素
-- $.name 对象属性
-- $[0] 数组元素
-- $.hobbies[*] 所有数组元素
-- 常用 JSON 函数
SELECT
JSON_EXTRACT(data, '$.name') AS name, -- 提取值
JSON_UNQUOTE(JSON_EXTRACT(data, '$.name')) AS name_unquoted, -- 去引号
JSON_TYPE(data) AS type, -- 类型
JSON_CONTAINS(data, '"张三"', '$.name') AS contains, -- 是否包含
JSON_SEARCH(data, 'one', '张三') AS search -- 搜索路径
FROM json_data;
-- 修改 JSON 数据
UPDATE json_data
SET data = JSON_SET(data, '$.age', 26)
WHERE id = 1;
UPDATE json_data
SET data = JSON_ARRAY_APPEND(data, '$.hobbies', '编程')
WHERE id = 1;
JSON 函数一览
| 函数 | 说明 |
|---|---|
JSON_EXTRACT(json, path) | 提取值 |
JSON_UNQUOTE(json) | 去除引号 |
JSON_TYPE(json) | 返回类型 |
JSON_ARRAY(...) | 创建数组 |
JSON_OBJECT(...) | 创建对象 |
JSON_MERGE_PRESERVE(json1, json2) | 合并 JSON |
JSON_SET(json, path, value) | 设置值 |
JSON_INSERT(json, path, value) | 插入值 |
JSON_REPLACE(json, path, value) | 替换值 |
JSON_REMOVE(json, path) | 删除值 |
JSON_CONTAINS(json, value, path) | 是否包含 |
JSON_SEARCH(json, mode, value) | 搜索 |
ENUM 和 SET 类型
ENUM 类型
枚举类型,只能选择列出的值之一:
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
status ENUM('active', 'inactive', 'banned') DEFAULT 'active',
gender ENUM('male', 'female', 'other')
);
INSERT INTO users (name, status, gender) VALUES ('张三', 'active', 'male');
-- ENUM 存储为整数(从 1 开始)
SELECT status, status + 0 AS status_int FROM users;
-- 使用数值插入
INSERT INTO users (name, status) VALUES ('李四', 1); -- 'active'
-- 查询枚举值列表
SHOW COLUMNS FROM users LIKE 'status';
ENUM 优缺点:
优点:
- 存储紧凑(1-2 字节)
- 数据验证
缺点:
- 修改需要 ALTER TABLE
- 查询结果为数字需要转换
SET 类型
集合类型,可以选择多个值:
CREATE TABLE articles (
id INT PRIMARY KEY,
title VARCHAR(200),
tags SET('技术', '生活', '旅行', '美食', '编程')
);
INSERT INTO articles (title, tags) VALUES ('MySQL 教程', '技术,编程');
INSERT INTO articles (title, tags) VALUES ('周末游记', '生活,旅行');
-- 查询包含特定标签的文章
SELECT * FROM articles WHERE FIND_IN_SET('技术', tags) > 0;
-- 使用位运算查询
SELECT * FROM articles WHERE tags & 1; -- '技术' 是第 1 位
数据类型选择原则
整数选择
-- 根据数值范围选择最小类型
age TINYINT UNSIGNED -- 0-255,足够存储年龄
year SMALLINT UNSIGNED -- 0-65535,足够存储年份
view_count INT UNSIGNED -- 0-42亿,适合访问量
big_id BIGINT UNSIGNED -- 超大数字
字符串选择
-- 固定长度用 CHAR
phone CHAR(11) -- 手机号
id_card CHAR(18) -- 身份证号
md5 CHAR(32) -- MD5 哈希
-- 变长用 VARCHAR
name VARCHAR(50) -- 姓名
email VARCHAR(100) -- 邮箱
title VARCHAR(200) -- 标题
-- 长文本用 TEXT
content TEXT -- 文章内容
日期时间选择
-- 只需日期
birth_date DATE
-- 需要日期和时间
created_at DATETIME -- 范围大,不受时区影响
-- 需要时区支持
event_time TIMESTAMP -- 自动时区转换
-- 只需年份
year_value YEAR
小数选择
-- 金额计算(必须精确)
price DECIMAL(10, 2)
salary DECIMAL(12, 2)
-- 科学计算(允许近似)
rate DOUBLE
ratio FLOAT
小结
本章我们学习了:
- 数值类型:整数、浮点数、定点数、BIT
- 字符串类型:CHAR、VARCHAR、TEXT、BLOB
- 日期时间类型:DATE、TIME、DATETIME、TIMESTAMP、YEAR
- JSON 类型:JSON 数据存储和操作函数
- ENUM 和 SET:枚举和集合类型
- 类型选择原则:根据实际需求选择合适的类型
练习
- 创建一个用户表,选择合适的数据类型存储各种用户信息
- 设计一个订单表,正确处理金额和时间字段
- 使用 JSON 类型存储用户配置信息
- 比较 DATETIME 和 TIMESTAMP 在不同时区下的行为