首页 / MySQL 入门教程 / 数值数据类型

MySQL 入门教程

数值数据类型

本教程共 46 篇 · 第 7 篇 · 更新于 2026-07-30 · 约 13 分钟阅读

MySQLMySQL 入门教程数据类型数值类型INTDECIMALBITUNSIGNED

7. 数值数据类型

本节目标:搞懂 MySQL 存数字的各种类型,整数怎么选、定点数和浮点数有什么区别、UNSIGNED 怎么用、BIT 干嘛的,学会按业务场景挑对类型,避免存错和浪费空间。

建表时每列都要指定类型。数值是最常用的一类,从用户 ID、年龄到金额、评分都靠它。这一节把数值类型一次讲透。

7.1 数值类型分两大类

MySQL 的数值类型分成两大阵营:

  • 精确数值:整数和定点数,存什么就是什么,不丢精度;
  • 近似数值:浮点数,存的是近似值,有微小误差。

涉及钱、计数、ID 这类必须精确的,用精确数值。科学计算、统计估算这类允许微小误差的,才考虑浮点数。

7.2 整数类型:五个档位

MySQL 的整数类型按”能存多大”分了五个档,加上标准 SQL 的 INTEGER。存储空间和取值范围对比如下:

类型存储(字节)有符号范围无符号范围(UNSIGNED)
TINYINT1-128 ~ 1270 ~ 255
SMALLINT2-32768 ~ 327670 ~ 65535
MEDIUMINT3-8388608 ~ 83886070 ~ 16777215
INT4-21亿 ~ 21亿0 ~ 42亿
BIGINT8约 -922亿亿 ~ 922亿亿0 ~ 1844亿亿
Note

INTINTEGER 是同义词,写哪个都行。MEDIUMINT 是 MySQL 扩展,标准 SQL 没有。

怎么选整数类型

选型原则就一句话:够用就行,别贪大。类型越大,占空间越多,索引也越大,查询越慢。

  • 状态、性别、是否删除这类小范围标志:TINYINT
  • 年龄、小计数:TINYINTSMALLINT
  • 用户 ID、订单 ID:INTBIGINT。中小项目 INT(42 亿)够用,海量数据用 BIGINT
  • 千万别所有 ID 都用 BIGINT,浪费空间。

7.3 UNSIGNED:只存非负数

UNSIGNED 关键字,把负数那部分空间让给正数,上限翻倍:

CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    age TINYINT UNSIGNED
);
  • idINT UNSIGNED:范围 0~42 亿,全是正数,适合自增主键;
  • ageTINYINT UNSIGNED:范围 0~255,存年龄绰绰有余。
Tip
  • 自增主键、计数器这类不可能为负的字段,加 UNSIGNED 是好习惯,能多用一倍空间。

7.4 显示宽度已被弃用

老教程里常看到 INT(11) 这种写法,括号里的 11显示宽度

注意:显示宽度不限制能存多大的数INT(11)INT 存储范围完全一样,那个 11 只是告诉某些客户端”显示时补足几位”。

从 MySQL 8.0.17 起,显示宽度被弃用(deprecated),写 INT(11) 会被警告。26.7 里直接写 INT 就行:

-- 旧写法,已弃用
age INT(11)

-- 正确写法
age INT
Warning

ZEROFILL(前导零填充)属性也一并被弃用了。要补零就用 LPAD() 函数在查询时处理,别再用 ZEROFILL

7.5 定点数 DECIMAL:钱必须用它

DECIMAL(定点数) 用来存绝对精确的小数,比如金额。它用 DECIMAL(P, D) 的形式定义:

  • P:精度(precision),总位数,1~65;
  • D:标度(scale),小数点后位数,0~30,且 D <= P

举例:

CREATE TABLE orders (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    amount DECIMAL(10, 2) NOT NULL
);

DECIMAL(10, 2) 表示总共 10 位、小数点后 2 位。能存的最大值是 99999999.99,适合存金额到分。

INSERT INTO orders(amount) VALUES(99.50), (100), (0.1);

mysql> SELECT amount FROM orders;
+--------+
| amount |
+--------+
|  99.50 |
| 100.00 |
|   0.10 |
+--------+

注意 100 存进去会变成 100.00,自动补齐小数位。存进去是什么样,取出来就是什么样,不会丢精度

Note

DECIMALNUMERICDEC 是同义词。DECIMAL(P) 等价于 DECIMAL(P, 0),纯整数。DECIMAL 不写参数默认 DECIMAL(10, 0)

为什么金额不能用浮点数

浮点数用二进制存小数,很多十进制小数没法精确表示,会有微小误差:

mysql> SELECT 0.1 + 0.2;
+--------------------+
| 0.1 + 0.2          |
+--------------------+
| 0.30000000000000004 |
+--------------------+

0.1 + 0.2 居然不等于 0.3!这就是浮点误差。金额要是这么算,账迟早对不上。所以凡是涉及钱的,一律用 DECIMAL

Tip
  • 金额推荐 DECIMAL(19, 4):能存到万分位,符合财务规范。日常用 DECIMAL(10, 2) 也够。

7.6 浮点数 FLOAT 和 DOUBLE

浮点数存的是近似值,适合科学计算、统计这种允许误差的场景。

类型存储精度
FLOAT4 字节单精度,约 6~7 位有效数字
DOUBLE8 字节双精度,约 15 位有效数字
CREATE TABLE sensors (
    id INT AUTO_INCREMENT PRIMARY KEY,
    temperature FLOAT,
    pressure DOUBLE
);

浮点数也可以写 FLOAT(P, D),但和 DECIMAL 的 P, D 含义略有不同,实际很少这么用,一般直接写 FLOATDOUBLE

Warning

别用浮点数存钱!前面那个 0.1+0.2 的例子就是教训。浮点数适合存温度、经纬度、传感器读数这类”本来就是近似值”的数据。

7.7 DECIMAL vs FLOAT vs DOUBLE 对比

对比项DECIMALFLOATDOUBLE
是否精确精确近似近似
存储变长(按位数)4 字节8 字节
计算速度较慢(要解码)
典型用途金额、计数科学计算高精度科学计算

一句话总结:要精确就用 DECIMAL,要快且允许误差就用 FLOAT/DOUBLE

7.8 BIT 类型:位字段

BIT(M) 用来存位字段M 是位数,1~64。它本质是存一串二进制位,常用来存一组开关标志。

CREATE TABLE user_flags (
    id INT PRIMARY KEY,
    permissions BIT(8)  -- 8 位,可表示 8 个开关
);

插入时用 b'...' 写二进制字面量:

INSERT INTO user_flags VALUES(1, b'10101010');

mysql> SELECT permissions + 0 FROM user_flags WHERE id = 1;
+------------------+
| permissions + 0  |
+------------------+
|              170 |
+------------------+

b'10101010' 转成十进制就是 170。直接 SELECT permissions 会显示成特殊字符,加 + 0 才能看到十进制值。

Note

BIT 用得不多,新手了解即可。大多数场景用 TINYINT 存 0/1 标志更直观。

7.9 BOOLEAN 其实是 TINYINT

MySQL 没有真正的 BOOLEAN 类型BOOLBOOLEANTINYINT(1) 的别名:

CREATE TABLE users (
    id INT PRIMARY KEY,
    is_active BOOLEAN
);

存进去的是 0 或 1(TRUE 等于 1,FALSE 等于 0):

INSERT INTO users VALUES(1, TRUE), (2, FALSE);

mysql> SELECT id, is_active FROM users;
+----+-----------+
| id | is_active |
+----+-----------+
|  1 |         1 |
|  2 |         0 |
+----+-----------+

查的时候用 WHERE is_active = TRUEWHERE is_active = 1 都行,效果一样。

7.10 数值溢出怎么处理

如果插入的值超过了类型范围,MySQL 的行为取决于 SQL 模式:

  • 严格模式(默认):直接报错,拒绝插入;
  • 非严格模式:截断到范围的边界值,给个警告。
-- age 是 TINYINT UNSIGNED(0~255)
INSERT INTO users(age) VALUES(300);

严格模式下报错:

ERROR 1264 (22003): Out of range value for column 'age' at row 1
Tip
  • 8.0+ 默认就是严格模式,溢出会报错而不是悄悄截断,这能避免脏数据。生产环境一定要保持严格模式。

7.11 数值类型选型建议

把这一节的选型原则归纳成几条:

  1. 整数够用就行:小范围用 TINYINT,ID 用 INT,海量数据 ID 用 BIGINT
  2. 不可能为负就加 UNSIGNED:主键、计数都加上;
  3. 金额一律 DECIMALDECIMAL(19, 4)DECIMAL(10, 2),别用浮点数;
  4. 科学计算用 FLOAT/DOUBLE:温度、坐标、传感器数据;
  5. 布尔值用 BOOLEAN(实际是 TINYINT);
  6. 别写显示宽度:写 INT 别写 INT(11),8.0.17 起已弃用;
  7. 能用整数别用字符串:用 INT 存状态码,别用 '1''2' 这种字符串。

7.12 小结

这一节搞定了数值类型:

  • 整数五档:TINYINT < SMALLINT < MEDIUMINT < INT < BIGINT,按需选;
  • UNSIGNED 只存非负数,上限翻倍,主键常用;
  • 显示宽度 INT(11) 已弃用,直接写 INT
  • DECIMAL(P,D) 存精确小数,金额必用;
  • FLOAT/DOUBLE 存近似值,科学计算用;
  • BIT 存位字段,BOOLEANTINYINT 别名;
  • 溢出在严格模式下报错,保持严格模式防脏数据。

下一节讲字符串类型,这是建表时用得最多的另一大类。