SQL基础⑩ | 数据类型篇
0 序言
本文将系统讲解MySQL中各类数据类型的定义、特点、属性及适用场景
,包括整数
、浮点
、日期时间
、字符串
等类型。
通过实例说明不同类型的用法及选择依据,读完后能掌握在实际开发中如何根据需求正确选择和使用数据类型
。
1 MySQL中的数据类型概述
MySQL支持多种数据类型,按用途可分为以下类别,每种类型适用于不同场景:
类型分类 | 具体类型示例 |
---|---|
整数类型 | TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)、BIGINT |
浮点类型 | FLOAT、DOUBLE |
定点数类型 | DECIMAL |
位类型 | BIT |
日期时间类型 | YEAR、TIME、DATE、DATETIME、TIMESTAMP |
文本字符串类型 | CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、ENUM、SET |
二进制字符串类型 | BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB |
JSON类型 | JSON对象、JSON数组 |
空间数据类型 | 单值类型(GEOMETRY、POINT等)、集合类型(MULTIPOINT、MULTIPOLYGON等) |
常见数据类型属性如下:
属性关键字 | 含义说明 |
---|---|
NULL | 字段允许包含NULL值 |
NOT NULL | 字段不允许包含NULL值 |
DEFAULT | 字段的默认值 |
PRIMARY KEY | 主键(唯一标识记录) |
AUTO_INCREMENT | 自动递增(仅适用于整数类型) |
UNSIGNED | 无符号(非负数值) |
CHARACTER SET name | 指定字段的字符集 |
2 整数类型
整数类型用于存储整数值,根据取值范围和存储字节不同分为5种
,适用于不同精度需求的场景。
2.1 类型介绍
各整数类型的取值范围和存储字节如下:
类型 | 有符号取值范围 | 无符号取值范围 | 存储字节 |
---|---|---|---|
TINYINT | -128~127 | 0~255 | 1 |
SMALLINT | -32768~32767 | 0~65535 | 2 |
MEDIUMINT | -8388608~8388607 | 0~16777215 | 3 |
INT(INTEGER) | -2147483648~2147483647 | 0~4294967295 | 4 |
BIGINT | -9223372036854775808~9223372036854775807 | 0~18446744073709551615 | 8 |
2.2 可选属性
整数类型有三个常用可选属性,用于调整显示和存储规则:
2.2.1 M(显示宽度)
- 定义:表示显示宽度,取值范围
(0,255)
,需配合ZEROFILL
使用才有效。 - 作用:当数值宽度小于M时,用0在左侧填充(仅影响显示,不改变实际存储)。
- 注意:从MySQL 8.0.17开始不推荐使用,且不影响数据实际存储范围。
2.2.2 UNSIGNED(无符号)
- 定义:表示字段值为非负数,最小取值为0。
- 示例:
INT UNSIGNED
的取值范围为0~4294967295
。
2.2.3 ZEROFILL(0填充)
- 定义:自动为数值左侧填充0至指定宽度(M),且自动添加
UNSIGNED
属性。 - 示例:
CREATE TABLE test_int2 (f1 INT(5),f2 INT(5) ZEROFILL ); INSERT INTO test_int2(f1, f2) VALUES(123, 123);
查询结果:f1=123,f2=00123(ZEROFILL生效)
2.3 适用场景与选择建议
- TINYINT:适用于枚举值(如状态码0-1)。
- SMALLINT:适用于小范围统计(如库存数量)。
- MEDIUMINT:适用于中等规模数据(如每日客流量)。
- INT:最常用,适用于多数整数场景(如商品编号)。
- BIGINT:适用于超大整数(如交易量、点击量)。
选择原则:优先保证取值范围足够
(避免溢出),再考虑节省存储空间。
3 浮点类型
浮点类型用于存储带小数的数值
,但存在精度误差,适用于对精度要求不高的场景。
3.1 类型介绍
MySQL支持的浮点类型及特点如下:
类型 | 有符号取值范围 | 无符号取值范围(非负部分) | 存储字节 |
---|---|---|---|
FLOAT | (-3.402823466E+38, -1.175494351E-38)、0、(1.175494351E-38, 3.402823466E+38) | 0、(1.175494351E-38, 3.402823466E+38) | 4 |
DOUBLE | (-1.7976931348623157E+308, -2.2250738585072014E-308)、0、(2.2250738585072014E-308, 1.7976931348623157E+308) | 0、(2.2250738585072014E-308, 1.7976931348623157E+308) | 8 |
- REAL:默认等同于DOUBLE,启用
REAL_AS_FLOAT
模式后等同于FLOAT。
3.2 精度说明
- 非标准语法:
FLOAT(M,D)
或DOUBLE(M,D)
,其中M为总位数(整数+小数),D为小数位数(D≤M≤255
,0≤D≤30
)。- 示例:
FLOAT(5,2)
表示取值范围-999.99~999.99。
- 示例:
- 精度误差:浮点类型通过二进制存储,可能无法精确表示某些十进制小数(如0.47+0.44+0.19可能计算为1.099999…)。
- 注意:从MySQL 8.0.17开始不推荐使用
(M,D)
和UNSIGNED
。
一般来说,会比较适用于科学计算等可容忍微小误差的场景,
不适合金融等高精度需求(如金额计算)
反正就是高精度的场合就不是很推荐使用。
4 定点数类型(DECIMAL)
定点数类型用于存储高精度小数
,无精度误差,适用于对精度要求极高的场景
。
4.1 类型介绍
- 语法:
DECIMAL(M,D)
,其中M为总位数(0≤M≤65),D为小数位数(0≤D≤30,D<M)。 - 存储:以字符串形式存储,存储空间为
M+2字节
,取值范围由M和D决定(如DECIMAL(5,2)
范围为-999.99~999.99)。 - 特点:精准无误差,适合
金额
等场景。
4.2 示例
CREATE TABLE test_decimal1 (f1 DECIMAL, -- 默认为DECIMAL(10,0)f2 DECIMAL(5,2)
);
INSERT INTO test_decimal1(f2) VALUES(123.456); -- 自动四舍五入为123.46
4.3 与浮点类型的区别
类型 | 精度 | 取值范围 | 适用场景 |
---|---|---|---|
FLOAT/DOUBLE | 有误差 | 范围大 | 科学计算(容忍误差) |
DECIMAL | 无误差 | 范围由M,D决定 | 金融、金额等高精度场景 |
5 位类型(BIT)
位类型用于存储二进制值,适用于存储开关状态等简单二进制数据。
5.1 类型介绍
- 语法:
BIT(M)
,M为二进制位数(1≤M≤64),默认M=1。 - 存储:占用
(M+7)/8
字节(如BIT(5)
占用1字节)。
5.2 示例
CREATE TABLE test_bit1 (f1 BIT, -- 1位,只能存0或1f2 BIT(5) -- 5位,取值范围0~31
);
INSERT INTO test_bit1(f2) VALUES(23); -- 23的二进制为10111,符合5位范围
SELECT BIN(f2) FROM test_bit1; -- 输出10111(二进制)
SELECT f2 + 0 FROM test_bit1; -- 输出23(十进制)
6 日期时间类型
日期时间类型用于存储时间相关数据
,包括年、月、日、时、分、秒等信息。
6.1 类型介绍
各日期时间类型的特点如下:
类型 | 格式 | 取值范围 | 存储字节 | 用途 |
---|---|---|---|---|
YEAR | YYYY | 1901~2155 | 1 | 存储年份 |
TIME | HH:MM:SS | -838:59:59~838:59:59 | 3 | 存储时间或时间间隔 |
DATE | YYYY-MM-DD | 1000-01-01~9999-12-31 | 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 UTC~2038-01-19 03:14:07 UTC | 4 | 带时区的日期+时间 |
6.2 DATETIME 与 TIMESTAMP的关键区别
- 时区相关性:TIMESTAMP会随时区变化,DATETIME固定不变。
- 存储方式:TIMESTAMP存储毫秒值(距1970-01-01),DATETIME存储字符串。
- 范围:DATETIME范围更大,TIMESTAMP适合跨时区场景。
示例:
CREATE TABLE temp_time (d1 DATETIME,d2 TIMESTAMP
);
INSERT INTO temp_time VALUES('2021-09-02 14:45:52', '2021-09-02 14:45:52');
SET time_zone = '+9:00'; -- 切换时区
SELECT * FROM temp_time; -- d1不变,d2变为15:45:52(时区+1)
运行后当你切换时区时,
d1的时间仍然为你放入的时间数据,
然后d2的时间会发生更改。
6.3 适用场景
- DATETIME:最常用,适用于多数需完整日期时间的场景,如注册时间可以用。
- TIMESTAMP:适用于跨时区系统,如全球业务日志等范围比较广的场景。
- YEAR/DATE/TIME:仅需单独存储年、日期或时间时使用。
7 文本字符串类型
文本字符串类型用于存储字符数据
,包括固定长度
、可变长度
、大文本
等类型。
7.1 CHAR与VARCHAR
类型 | 特点 | 长度范围 | 存储空间 | 适用场景 |
---|---|---|---|---|
CHAR(M) | 固定长度 | 0≤M≤255 | M字节(尾部空格会被截断) | 短字符串、长度固定(如邮编) |
VARCHAR(M) | 可变长度 | 0≤M≤65535 | 实际长度+1字节 | 长度不固定的字符串(如姓名) |
示例:
CREATE TABLE test_char1 (c1 CHAR(1),c2 CHAR(5)
);
INSERT INTO test_char1 VALUES('a', 'Tom');
SELECT CONCAT(c2, '***') FROM test_char1; -- 输出'Tom***'(c2自动补空格后截断)
详细分析可见下图。
7.2 TEXT类型
TEXT类型用于存储大文本数据
,无需指定长度,按存储容量分为4种:
类型 | 长度范围 | 存储空间 | 用途 |
---|---|---|---|
TINYTEXT | 0≤L≤255 | L+2字节 | 短文本(如备注) |
TEXT | 0≤L≤65535 | L+2字节 | 普通文本(如文章) |
MEDIUMTEXT | 0≤L≤16777215 | L+3字节 | 中长文本(如日志) |
LONGTEXT | 0≤L≤4294967295 | L+4字节 | 超长文本(如文档) |
注意:TEXT类型不能作为主键
,检索效率低于CHAR/VARCHAR,建议大文本单独分表存储。
7.3 ENUM(枚举类型)
- 定义:只能从预定义值中选一个(单选),如
ENUM('春','夏','秋','冬')
。 - 存储:1或2字节(取决于成员数:1255个用1字节,25665535个用2字节)。
- 示例:
CREATE TABLE test_enum (season ENUM('春','夏','秋','冬') ); INSERT INTO test_enum VALUES('春'), (3); -- 3对应'秋'(索引从1开始)
7.4 SET(集合类型)
- 定义:可从预定义值中选
多个
(多选),如SET('A','B','C')
。 - 存储:18字节(取决于成员数:18个用1字节,9~16个用2字节,以此类推)。
- 示例:
CREATE TABLE test_set (s SET('A','B','C') ); INSERT INTO test_set VALUES('A,B'), ('A,B,C,A'); -- 重复值会自动去重
8 二进制字符串类型
二进制字符串类型用于存储二进制数据(如图片、音频),包括固定长度、可变长度和大二进制类型。
8.1 BINARY与VARBINARY
类型 | 特点 | 长度范围 | 存储空间 | 用途 |
---|---|---|---|---|
BINARY(M) | 固定长度 | 0≤M≤255 | M字节(补’\0’) | 短二进制(如哈希值) |
VARBINARY(M) | 可变长度 | 0≤M≤65535 | 实际长度+1字节 | 长度不固定的二进制 |
8.2 BLOB类型
BLOB类型用于存储大二进制数据
,按容量分为4种:
类型 | 长度范围 | 存储空间 | 用途 |
---|---|---|---|
TINYBLOB | 0≤L≤255 | L+1字节 | 短二进制(如图标) |
BLOB | 0≤L≤65535 | L+2字节 | 普通二进制(如小图片) |
MEDIUMBLOB | 0≤L≤16777215 | L+3字节 | 中长二进制(如音频) |
LONGBLOB | 0≤L≤4294967295 | L+4字节 | 超长二进制(如视频) |
注意:实际开发中通常将文件存储在磁盘,数据库仅存文件路径,避免数据库过大。
9 JSON类型
JSON类型用于存储JSON格式数据,支持自动验证和高效查询,适用于半结构化数据
。
9.1 示例
CREATE TABLE test_json (js JSON
);
INSERT INTO test_json VALUES ('{"name":"songhk", "age":18, "address":{"province":"beijing", "city":"beijing"}}'
);
-- 查询JSON字段中的值
SELECT js->'$.name' AS name, -- 返回带引号的结果(如"songhk")js->>'$.age' AS age -- 返回无引号的结果(如18)
FROM test_json;
这个了解一下就可以了,
思想类似的。
10 空间数据类型
空间数据类型用于存储地理信息(如位置、区域)
,基于OpenGIS标准,包括:
- 单值类型:
GEOMETRY(基类)
、POINT(点)、LINESTRING(线)、POLYGON(多边形)。 - 集合类型:
MULTIPOINT(多点)
、MULTILINESTRING(多线)、MULTIPOLYGON(多 polygon)等。
示例:
CREATE TABLE test_geo (g POINT -- 存储点坐标(经度 纬度)
);
INSERT INTO test_geo VALUES (POINT(121.21 31.23));
11 小结
MySQL数据类型丰富,选择时需结合以下原则:
- 精度优先:金融等
高精度场景用DECIMAL
,避免FLOAT/DOUBLE。 - 存储空间:根据数据范围选择最小合适类型(如用TINYINT存储状态码)。
- 查询效率:
短字符串优先用CHAR/VARCHAR
,大文本/二进制单独分表
。 - 业务场景:
跨时区用TIMESTAMP
,半结构化数据用JSON,地理信息用空间类型
。
这里一般来说,
如果是非负数,那就用UNSIGNED,
小数的话用DECIMAL,
长字符串超过5000时用TEXT并分表,
差不多就这些内容。