MySQL 数值类型

🎉摘要:本文详细解析MySQL四大数值类型:整数类型(TINYINT、SMALLINT、INT、BIGINT)、浮点类型(FLOAT、DOUBLE)、定点小数(DECIMAL)和位类型(BIT)。涵盖各类型存储空间、取值范围、精度特性及实际应用场景,提供电商系统等最佳实践案例,帮助开发者优化数据库存储与性能。

MySQL 数值分为 4 大类:整数类型、浮点类型、定点小数、位类型 BIT。数据类型的核心作用是控制存储空间、限制取值范围、保证计算精度、优化索引性能。

整数类型

MySQL 提供了五种整数类型,它们的区别在于取值范围和存储空间,如下表:

类型存储空间有符号范围无符号范围
TINYINT1字节-128 ~ 1270 ~ 255
SMALLINT2字节-32768 ~ 327670 ~ 65535
MEDIUMINT3字节-8388608 ~ 83886070 ~ 16777215
INT/INTEGER4字节-21亿 ~ 21亿0 ~ 43亿
BIGINT8字节极大范围极大范围

示例:使用上面的数据类型创建一张 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 是近似数值类型,存储的是浮点数,范围信息如下表:

类型存储空间有符号范围无符号范围
FLOAT4字节单精度浮点数-
DOUBLE8字节双精度浮点数-

示例:使用上面的数据类型创建一张数据表。

-- 创建测试表
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 基础语法: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,这样可以准确的表示金额,避免误差。

更多知识请阅读后续章节……谢谢!!!

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号