MySQL数据类型 #
一、数据类型概述 #
1.1 类型分类 #
text
MySQL数据类型
├── 数值类型
│ ├── 整数类型
│ │ ├── TINYINT
│ │ ├── SMALLINT
│ │ ├── MEDIUMINT
│ │ ├── INT
│ │ └── BIGINT
│ ├── 浮点类型
│ │ ├── FLOAT
│ │ └── DOUBLE
│ └── 定点类型
│ └── DECIMAL
├── 字符串类型
│ ├── CHAR
│ ├── VARCHAR
│ ├── TEXT系列
│ └── BLOB系列
├── 日期时间类型
│ ├── DATE
│ ├── TIME
│ ├── DATETIME
│ ├── TIMESTAMP
│ └── YEAR
├── JSON类型
│ └── JSON
└── 其他类型
├── BOOLEAN
├── ENUM
└── SET
二、整数类型 #
2.1 整数类型列表 #
| 类型 | 字节 | 有符号范围 | 无符号范围 |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2 | -32768 ~ 32767 | 0 ~ 65535 |
| MEDIUMINT | 3 | -8388608 ~ 8388607 | 0 ~ 16777215 |
| INT | 4 | -2147483648 ~ 2147483647 | 0 ~ 4294967295 |
| BIGINT | 8 | -2^63 ~ 2^63-1 | 0 ~ 2^64-1 |
2.2 整数类型使用 #
sql
-- 创建表
CREATE TABLE integers (
tiny_col TINYINT,
small_col SMALLINT,
medium_col MEDIUMINT,
int_col INT,
bigint_col BIGINT
);
-- 有符号整数(默认)
CREATE TABLE signed_int (
num INT
);
-- 无符号整数
CREATE TABLE unsigned_int (
num INT UNSIGNED
);
-- 显示宽度(不影响存储范围)
CREATE TABLE display_width (
num INT(5) ZEROFILL
);
INSERT INTO display_width VALUES (123);
-- 查询结果:00123
2.3 选择建议 #
| 场景 | 推荐类型 |
|---|---|
| 年龄 | TINYINT UNSIGNED |
| 状态标识 | TINYINT |
| 数量、计数 | INT |
| 主键ID | INT 或 BIGINT |
| 金额(分) | BIGINT |
三、浮点类型 #
3.1 浮点类型列表 #
| 类型 | 字节 | 说明 |
|---|---|---|
| FLOAT | 4 | 单精度浮点数 |
| DOUBLE | 8 | 双精度浮点数 |
3.2 浮点类型使用 #
sql
-- FLOAT类型
CREATE TABLE float_table (
price FLOAT,
weight FLOAT(5,2)
);
-- FLOAT(M,D)
-- M:总位数,D:小数位数
-- FLOAT(5,2):最多5位,小数2位,如:123.45
INSERT INTO float_table VALUES (123.456, 123.45);
-- price存储:约123.456(可能有精度损失)
-- weight存储:123.45
-- DOUBLE类型
CREATE TABLE double_table (
precise_value DOUBLE(10,6)
);
INSERT INTO double_table VALUES (123.456789);
-- 存储:123.456789
3.3 浮点精度问题 #
sql
-- 浮点数精度问题
SELECT 0.1 + 0.2 = 0.3; -- 结果:0(false)
-- 原因:浮点数存储有精度损失
SELECT 0.1 + 0.2; -- 结果:0.30000000000000004
-- 对于精确计算,使用DECIMAL
SELECT CAST(0.1 AS DECIMAL(10,1)) + CAST(0.2 AS DECIMAL(10,1)) = 0.3;
-- 结果:1(true)
四、定点类型 #
4.1 DECIMAL类型 #
sql
-- DECIMAL(M,D)
-- M:精度,总位数(1-65)
-- D:标度,小数位数(0-30)
CREATE TABLE decimal_table (
amount DECIMAL(10,2),
rate DECIMAL(5,4)
);
INSERT INTO decimal_table VALUES (12345678.90, 0.1234);
-- 精确计算
SELECT amount * rate FROM decimal_table;
-- 结果:1524156.751926(精确)
4.2 金额存储 #
sql
-- 推荐方案1:DECIMAL存储
CREATE TABLE orders (
id INT PRIMARY KEY,
amount DECIMAL(10,2) -- 单位:元
);
-- 推荐方案2:整数存储(分)
CREATE TABLE orders (
id INT PRIMARY KEY,
amount BIGINT -- 单位:分,12345表示123.45元
);
-- 查询时转换
SELECT amount / 100 AS amount_yuan FROM orders;
五、字符串类型 #
5.1 CHAR和VARCHAR #
| 类型 | 说明 | 最大长度 | 特点 |
|---|---|---|---|
| CHAR(N) | 定长字符串 | 255 | 不足补空格 |
| VARCHAR(N) | 变长字符串 | 65535 | 按实际存储 |
sql
-- CHAR类型
CREATE TABLE char_table (
code CHAR(10),
status CHAR(1)
);
INSERT INTO char_table VALUES ('ABC', 'A');
-- code存储:'ABC '(补空格到10位)
-- VARCHAR类型
CREATE TABLE varchar_table (
name VARCHAR(100),
description VARCHAR(500)
);
INSERT INTO varchar_table VALUES ('John', 'This is a description');
-- name存储:'John'(4字节)
5.2 TEXT类型 #
| 类型 | 最大长度 | 存储需求 |
|---|---|---|
| TINYTEXT | 255字节 | 1字节前缀 |
| TEXT | 65535字节 | 2字节前缀 |
| MEDIUMTEXT | 16MB | 3字节前缀 |
| LONGTEXT | 4GB | 4字节前缀 |
sql
CREATE TABLE articles (
id INT PRIMARY KEY,
title VARCHAR(200),
summary TEXT,
content LONGTEXT
);
-- TEXT类型不能有默认值
-- 错误:content TEXT DEFAULT ''
5.3 BLOB类型 #
| 类型 | 最大长度 | 说明 |
|---|---|---|
| TINYBLOB | 255字节 | 小型二进制 |
| BLOB | 65KB | 二进制大对象 |
| MEDIUMBLOB | 16MB | 中型二进制 |
| LONGBLOB | 4GB | 大型二进制 |
sql
CREATE TABLE files (
id INT PRIMARY KEY,
file_name VARCHAR(100),
file_data MEDIUMBLOB,
file_size INT
);
-- 存储图片、文件等二进制数据
5.4 字符串类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 固定长度(如手机号) | CHAR |
| 变长字符串 | VARCHAR |
| 长文本 | TEXT |
| 二进制文件 | BLOB |
六、日期时间类型 #
6.1 日期时间类型列表 #
| 类型 | 格式 | 范围 | 字节 |
|---|---|---|---|
| DATE | YYYY-MM-DD | 1000-01-01 ~ 9999-12-31 | 3 |
| TIME | HH:MM:SS | -838:59:59 ~ 838:59:59 | 3 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 | 8 |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 | 4 |
| YEAR | YYYY | 1901 ~ 2155 | 1 |
6.2 DATE类型 #
sql
CREATE TABLE date_table (
birth_date DATE,
event_date DATE
);
INSERT INTO date_table VALUES ('1990-05-15', '2024-12-31');
-- 使用函数
INSERT INTO date_table VALUES (CURRENT_DATE, CURDATE());
-- 日期格式
SELECT DATE_FORMAT(birth_date, '%Y年%m月%d日') FROM date_table;
-- 结果:1990年05月15日
6.3 TIME类型 #
sql
CREATE TABLE time_table (
start_time TIME,
duration TIME
);
INSERT INTO time_table VALUES ('09:30:00', '08:00:00');
-- 时间范围可以超过24小时(表示时长)
INSERT INTO time_table VALUES ('100:00:00', '200:30:00');
-- 使用函数
INSERT INTO time_table VALUES (CURRENT_TIME, NOW());
6.4 DATETIME类型 #
sql
CREATE TABLE datetime_table (
created_at DATETIME,
updated_at DATETIME
);
INSERT INTO datetime_table VALUES ('2024-01-15 10:30:00', NOW());
-- 自动初始化
CREATE TABLE auto_datetime (
id INT PRIMARY KEY,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO auto_datetime (id) VALUES (1);
-- created_at和updated_at自动设置为当前时间
UPDATE auto_datetime SET id = 2 WHERE id = 1;
-- updated_at自动更新为当前时间
6.5 TIMESTAMP类型 #
sql
CREATE TABLE timestamp_table (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- TIMESTAMP特点:
-- 1. 自动转换为UTC存储
-- 2. 查询时转换为当前时区
-- 3. 范围受限(到2038年)
-- 查看时区设置
SHOW VARIABLES LIKE '%time_zone%';
-- 设置时区
SET time_zone = '+8:00'; -- 东八区
SET time_zone = 'SYSTEM'; -- 系统时区
6.6 YEAR类型 #
sql
CREATE TABLE year_table (
birth_year YEAR,
publish_year YEAR(4)
);
INSERT INTO year_table VALUES (1990, 2024);
-- YEAR支持2位或4位
-- 2位年份:00-69转换为2000-2069,70-99转换为1970-1999
INSERT INTO year_table VALUES (24, 99);
-- 存储:2024, 1999
6.7 日期函数 #
sql
-- 当前日期时间
SELECT NOW(), CURRENT_TIMESTAMP, SYSDATE();
SELECT CURDATE(), CURRENT_DATE;
SELECT CURTIME(), CURRENT_TIME;
-- 日期计算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY); -- 加7天
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH); -- 减1个月
SELECT DATEDIFF('2024-12-31', '2024-01-01'); -- 计算天数差
-- 提取部分
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
SELECT HOUR(NOW()), MINUTE(NOW()), SECOND(NOW());
SELECT WEEKDAY(NOW()); -- 星期几(0=周一)
七、JSON类型 #
7.1 JSON类型特点 #
sql
CREATE TABLE json_table (
id INT PRIMARY KEY,
data JSON
);
-- 插入JSON数据
INSERT INTO json_table VALUES (
1,
'{"name": "John", "age": 30, "skills": ["MySQL", "Python"]}'
);
-- 插入JSON数组
INSERT INTO json_table VALUES (
2,
'[{"id": 1, "name": "A"}, {"id": 2, "name": "B"}]'
);
7.2 JSON函数 #
sql
-- 提取值
SELECT data->'$.name' FROM json_table WHERE id = 1;
SELECT data->>'$.name' FROM json_table WHERE id = 1; -- 去掉引号
-- JSON_EXTRACT函数
SELECT JSON_EXTRACT(data, '$.name') FROM json_table;
-- 提取数组元素
SELECT data->'$.skills[0]' FROM json_table WHERE id = 1;
-- 创建JSON
SELECT JSON_OBJECT('name', 'John', 'age', 30);
-- 结果:{"name": "John", "age": 30}
SELECT JSON_ARRAY(1, 2, 3, 'a', 'b');
-- 结果:[1, 2, 3, "a", "b"]
-- 合并JSON
SELECT JSON_MERGE_PRESERVE(
'{"a": 1}',
'{"b": 2}'
);
-- 结果:{"a": 1, "b": 2}
-- 设置值
UPDATE json_table
SET data = JSON_SET(data, '$.email', 'john@example.com')
WHERE id = 1;
-- 删除值
UPDATE json_table
SET data = JSON_REMOVE(data, '$.age')
WHERE id = 1;
7.3 JSON查询 #
sql
-- 按JSON字段查询
SELECT * FROM json_table WHERE data->'$.name' = '"John"';
-- 使用JSON_CONTAINS
SELECT * FROM json_table
WHERE JSON_CONTAINS(data->'$.skills', '"MySQL"');
-- 使用JSON_SEARCH
SELECT * FROM json_table
WHERE JSON_SEARCH(data, 'one', 'John') IS NOT NULL;
八、枚举和集合 #
8.1 ENUM类型 #
sql
CREATE TABLE enum_table (
id INT PRIMARY KEY,
status ENUM('active', 'inactive', 'pending'),
priority ENUM('low', 'medium', 'high') DEFAULT 'medium'
);
INSERT INTO enum_table (id, status) VALUES (1, 'active');
-- ENUM存储为整数索引
-- 'active'=1, 'inactive'=2, 'pending'=3
-- 查询索引值
SELECT status + 0 FROM enum_table;
-- 查询所有可能值
SELECT DISTINCT status FROM enum_table;
-- 使用数字插入
INSERT INTO enum_table (id, status) VALUES (2, 2); -- 'inactive'
8.2 SET类型 #
sql
CREATE TABLE set_table (
id INT PRIMARY KEY,
tags SET('tag1', 'tag2', 'tag3', 'tag4')
);
-- 可以存储多个值
INSERT INTO set_table VALUES (1, 'tag1,tag2');
INSERT INTO set_table VALUES (2, 'tag1,tag2,tag3');
-- 使用FIND_IN_SET查询
SELECT * FROM set_table WHERE FIND_IN_SET('tag1', tags) > 0;
-- 使用位运算
SELECT * FROM set_table WHERE tags & 1; -- 包含tag1
九、布尔类型 #
9.1 BOOLEAN类型 #
sql
-- BOOLEAN是TINYINT(1)的别名
CREATE TABLE bool_table (
id INT PRIMARY KEY,
is_active BOOLEAN,
is_deleted BOOLEAN DEFAULT FALSE
);
INSERT INTO bool_table (id, is_active) VALUES (1, TRUE);
INSERT INTO bool_table (id, is_active) VALUES (2, FALSE);
-- 查询
SELECT * FROM bool_table WHERE is_active = TRUE;
SELECT * FROM bool_table WHERE is_active IS TRUE;
SELECT * FROM bool_table WHERE is_active;
十、类型转换 #
10.1 隐式转换 #
sql
-- 字符串转数字
SELECT '123' + 0; -- 结果:123
SELECT '123abc' + 0; -- 结果:123
-- 数字转字符串
SELECT CONCAT(123, 'abc'); -- 结果:'123abc'
-- 日期转换
SELECT '2024-01-01' + INTERVAL 1 DAY;
10.2 显式转换 #
sql
-- CAST函数
SELECT CAST('123' AS SIGNED);
SELECT CAST('123.45' AS DECIMAL(10,2));
SELECT CAST(123 AS CHAR);
SELECT CAST(NOW() AS DATE);
-- CONVERT函数
SELECT CONVERT('123', SIGNED);
SELECT CONVERT('abc' USING utf8mb4);
-- 常用转换
SELECT
CAST('2024-01-15' AS DATE),
CAST('10:30:00' AS TIME),
CAST('2024-01-15 10:30:00' AS DATETIME);
十一、类型选择建议 #
11.1 数值类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 主键 | INT / BIGINT |
| 年龄 | TINYINT UNSIGNED |
| 数量 | INT |
| 金额 | DECIMAL |
| 科学计算 | DOUBLE |
11.2 字符串类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 手机号 | CHAR(11) |
| 邮箱 | VARCHAR(100) |
| 用户名 | VARCHAR(50) |
| 文章内容 | TEXT |
| 文件数据 | BLOB |
11.3 时间类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 出生日期 | DATE |
| 创建时间 | DATETIME / TIMESTAMP |
| 时区敏感 | TIMESTAMP |
| 持续时间 | TIME |
| 年份 | YEAR |
十二、总结 #
数据类型选择要点:
| 类型 | 选择原则 |
|---|---|
| 整数 | 根据范围选择最小类型 |
| 小数 | 精确计算用DECIMAL |
| 字符串 | 定长用CHAR,变长用VARCHAR |
| 日期 | 考虑时区和范围 |
| JSON | 灵活数据结构 |
下一步,让我们学习数据库操作!
最后更新:2026-03-26