MySQL 数值分为 4 大类:整数类型、浮点类型、定点小数、位类型 BIT。数据类型的核心作用是控制存储空间、限制取值范围、保证计算精度、优化索引性能。
MySQL 提供了五种整数类型,它们的区别在于取值范围和存储空间,如下表:
| 类型 | 存储空间 | 有符号范围 | 无符号范围 |
| TINYINT | 1字节 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2字节 | -32768 ~ 32767 | 0 ~ 65535 |
| MEDIUMINT | 3字节 | -8388608 ~ 8388607 | 0 ~ 16777215 |
| INT/INTEGER | 4字节 | -21亿 ~ 21亿 | 0 ~ 43亿 |
| BIGINT | 8字节 | 极大范围 | 极大范围 |
示例:使用上面的数据类型创建一张 int_demo 表。
-- 创建一个测试表
mysql> CREATE TABLE int_demo (
-> a TINYINT COMMENT '小整数',
-> b SMALLINT COMMENT '短整数',
-> c MEDIUMINT COMMENT '中等整数',
-> d INT COMMENT '整数',
-> e BIGINT COMMENT '大整数'
-> );
Query OK, 0 rows affected (0.01 sec)
-- 插入测试数据
mysql> INSERT INTO int_demo VALUES (100, 1000, 100000, 1000000, 10000000000);
Query OK, 1 row affected (0.00 sec)
mysql> select * from int_demo;
+------+------+--------+---------+-------------+
| a | b | c | d | e |
+------+------+--------+---------+-------------+
| 100 | 1000 | 100000 | 1000000 | 10000000000 |
+------+------+--------+---------+-------------+
1 row in set (0.00 sec)数据类型的使用建议:
TINYINT:适用于状态标记(0/1)、性别(0/1/2)、评分(1-5星)等小范围整数
SMALLINT:适用于端口号(最大65535)、年份(存储1901-2155)、中小型网站的文章ID等
MEDIUMINT:这个类型比较尴尬,不太常用。MySQL 的文档推荐要么用 INT,要么用 SMALLINT。
INT:最常用的整数类型,能存到 21 亿,适用于大多数场景。
BIGINT:用于可能超过 21 亿的ID(如用户量大的系统)、时间戳的微秒级存储等。
有符号与无符号:
默认情况下整数是有符号的,可以存储负数。如果确定某个字段不会出现负数,可以指定为无符号,例如:
mysql> CREATE TABLE unsigned_demo (
-> age TINYINT UNSIGNED COMMENT '年龄,0-255',
-> score INT UNSIGNED COMMENT '积分,无负数'
-> );
Query OK, 0 rows affected (0.01 sec)
-- 插入正常数据
mysql> INSERT INTO unsigned_demo VALUES (25, 1000);
Query OK, 1 row affected (0.00 sec)
-- 这行会报错,因为不能为负数
mysql> INSERT INTO unsigned_demo VALUES (-1, 100);
ERROR 1264 (22003): Out of range value for column 'age' at row 1注意:在 MySQL 8.0.17 之后,不推荐使用显示宽度属性(如 INT(10)),这个值对存储和计算都没有影响,只是显示上的区别。
FLOAT 和 DOUBLE 是近似数值类型,存储的是浮点数,范围信息如下表:
| 类型 | 存储空间 | 有符号范围 | 无符号范围 |
| FLOAT | 4字节 | 单精度浮点数 | - |
| DOUBLE | 8字节 | 双精度浮点数 | - |
示例:使用上面的数据类型创建一张数据表。
-- 创建测试表
mysql> CREATE TABLE float_demo (
-> f FLOAT COMMENT '单精度浮点数',
-> d DOUBLE COMMENT '双精度浮点数',
-> e DECIMAL(10,2) COMMENT '定点数'
-> );
Query OK, 0 rows affected (0.01 sec)
-- 插入数据
mysql> INSERT INTO float_demo VALUES (0.1 + 0.2, 0.1 + 0.2, 3.1415);
Query OK, 1 row affected, 1 warning (0.00 sec)
-- 查询结果会发现精度问题
mysql> SELECT * FROM float_demo;
+------+------+------+
| f | d | e |
+------+------+------+
| 0.3 | 0.3 | 3.14 |
+------+------+------+
1 row in set (0.00 sec)注意:浮点数的特点是存储空间小、计算速度快,但存在精度问题。这是因为计算机内部使用二进制表示小数,很多十进制小数无法精确表示,都是近似表示。
浮点数适用场景如下:
科学计算中对精度要求不高的场景
存储传感器读数、统计数据等允许微小误差的数据
游戏开发中的坐标、速度等
浮点数不适用场景:
财务数据(金额、价格)
需要精确比较的场景
DECIMAL 是精确数值类型,适合存储需要精确计算的数据,例如存储金额。
DECIMAL 基础语法:DECIMAL(M, D)
M:总有效数字位数(整数位 + 小数位),最大取值 65
D:小数部分位数,最大取值 30,且 D ≤ M
例如,DECIMAL(10, 2) 可以存储 -99999999.99 到 99999999.99。下面将创建示例数据表:
-- 创建数据表
mysql> CREATE TABLE decimal_demo (
-> price DECIMAL(10, 2) COMMENT '价格,最大99999999.99',
-> amount DECIMAL(12, 4) COMMENT '金额,支持4位小数'
-> );
Query OK, 0 rows affected (0.01 sec)
-- 插入数据
mysql> INSERT INTO decimal_demo VALUES (99999999.99, 12345678.9999);
Query OK, 1 row affected (0.00 sec)
-- 精确计算
mysql> select * from decimal_demo;
+-------------+---------------+
| price | amount |
+-------------+---------------+
| 99999999.99 | 12345678.9999 |
+-------------+---------------+
1 row in set (0.00 sec)
mysql> SELECT price * 3 FROM decimal_demo;
+--------------+
| price * 3 |
+--------------+
| 299999999.97 |
+--------------+
1 row in set (0.00 sec)DECIMAL 和 DOUBLE 比较:
-- 创建数据表
mysql> CREATE TABLE compare_demo (
-> d DECIMAL(10, 4),
-> f DOUBLE
-> );
Query OK, 0 rows affected (0.03 sec)
-- 插入数据
mysql> INSERT INTO compare_demo VALUES (0.29, 0.29);
Query OK, 1 row affected (0.00 sec)
-- 查询数据表的数据
mysql> select * from compare_demo;
+--------+------+
| d | f |
+--------+------+
| 0.2900 | 0.29 |
+--------+------+
1 row in set (0.00 sec)
-- 比较结果
SELECT * FROM compare_demo WHERE d = 0.3; -- 能查到
SELECT * FROM compare_demo WHERE f = 0.3; -- 查不到(精度问题)下面通过电商系统中的表来演示如何正确的选择数值类型,例如:
mysql> CREATE TABLE numeric_best_practice (
-> -- 自增ID,大系统用BIGINT
-> product_id BIGINT AUTO_INCREMENT PRIMARY KEY,
->
-> -- 状态、类型等小范围整数用TINYINT
-> status TINYINT UNSIGNED COMMENT '0下架,1上架,2删除',
-> sort_order TINYINT UNSIGNED COMMENT '排序,一般0-255足够',
->
-> -- 数量、计数用INT
-> stock INT COMMENT '库存数量',
-> sold_count INT UNSIGNED COMMENT '销量',
-> view_count INT UNSIGNED COMMENT '浏览量',
->
-> -- 所有金额用DECIMAL
-> price DECIMAL(10, 2) COMMENT '售价,最大千万级别',
-> market_price DECIMAL(10, 2) COMMENT '市场价',
-> cost_price DECIMAL(10, 2) COMMENT '成本价',
->
-> -- 重量、尺寸可能有小数,根据精度要求选择
-> weight DECIMAL(8, 3) COMMENT '重量(kg),3位小数',
-> length DECIMAL(6, 2) COMMENT '长度(cm),2位小数',
->
-> -- 评分等用DECIMAL保证精度
-> rating DECIMAL(2, 1) COMMENT '评分,如4.5',
->
-> -- 折扣率用DECIMAL
-> discount_rate DECIMAL(3, 2) COMMENT '折扣率,如0.85表示85折'
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)上面表中:
自增 ID 使用 BIGINT,可避免 ID 用尽。
状态、排序则使用 tinyint,可以减少存储空间。
数量和计数使用整数。
金额使用 decimal,这样可以准确的表示金额,避免误差。
更多知识请阅读后续章节……谢谢!!!