数值类型
导学
选错数值类型会导致空间浪费、精度丢失,甚至数据溢出。本节系统讲解 MySQL 5.7 的整数和浮点类型,帮你建立"该用什么类型"的判断力。
定义
数值类型:用于存储整数、定点数、浮点数的数据类型。MySQL 5.7 提供整数类型(TINYINT 到 BIGINT)、定点数(DECIMAL)、浮点数(FLOAT、DOUBLE)。
整数类型
| 类型 | 有符号范围 | 无符号范围 | 存储空间 |
|---|---|---|---|
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 字节 |
整数类型范围演示
当前数据状态:
CREATE TABLE employees (
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20),
dept VARCHAR(20),
score DECIMAL(5,2)
);
INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);
当前表数据:
| emp_id | emp_name | dept | score |
|---|---|---|---|
| 1 | 大翔 | 技术部 | 100 |
| 2 | 白歌 | 技术部 | NULL |
emp_id 使用 INT 类型,score 使用 DECIMAL(5,2) 类型。
验证范围边界:
-- TINYINT UNSIGNED 最大值为 255
SELECT CAST(255 AS TINYINT UNSIGNED) AS max_tinyint;
-- INT UNSIGNED 最大值为 4294967295
SELECT CAST(4294967295 AS INT UNSIGNED) AS max_int;
结果:
| max_tinyint | max_int |
|---|---|
| 255 | 4294967295 |
溢出警告演示:
-- 有符号 TINYINT 最大值为 127,128 会溢出
SELECT CAST(128 AS TINYINT) AS overflow_demo;
结果:
| overflow_demo |
|---|
| 127 |
结果解读:CAST(128 AS TINYINT) 中,TINYINT 是有符号类型,范围 -128 ~ 127,128 超出范围被截断为最大值 127。生产环境中,超出范围的插入在严格模式下会产生错误。
选型建议:
- 状态标志、布尔值:
TINYINT(MySQL 没有真正的布尔类型,BOOL是TINYINT(1)的别名) - 年龄、小范围计数:
TINYINT UNSIGNED - 常规主键、行数:
INT UNSIGNED(42 亿足够绝大多数场景) - 分布式 ID、时间戳、大数量统计:
BIGINT UNSIGNED
易错点:
INT(11)中的11只是显示宽度提示,不影响存储范围或性能。配合ZEROFILL时才影响显示,但ZEROFILL会隐式添加UNSIGNED。
INT(M) 显示宽度演示
CREATE TABLE zerofill_demo (
id1 INT(5),
id2 INT(5) ZEROFILL,
id3 INT
);
INSERT INTO zerofill_demo VALUES (123, 123, 123);
SELECT * FROM zerofill_demo;
结果:
| id1 | id2 | id3 |
|---|---|---|
| 123 | 00123 | 123 |
结果解读:INT(5) ZEROFILL 会在显示时左侧补零到 5 位宽度,但存储空间和数值范围与 INT 完全相同。id2 显示为 00123,但实际存储的值仍是 123。
定点数 DECIMAL
DECIMAL(M, D)
M:总精度(总位数),最大 65D:小数位数,最大 30
适用场景:货币、金额、税率等对精度要求严格的场景。绝不使用 FLOAT/DOUBLE 存金额。
DECIMAL 精度演示
DECIMAL(M, D) 中 M 为总精度(最大 65),D 为小数位数(最大 30)。
适用场景:货币、金额、税率等对精度要求严格的场景。绝不使用 FLOAT/DOUBLE 存金额。
DECIMAL(10, 2) 可存储 -99999999.99 到 99999999.99。
浮点数 FLOAT / DOUBLE
| 类型 | 精度 | 存储空间 |
|---|---|---|
FLOAT | 单精度,约 7 位有效数字 | 4 字节 |
DOUBLE | 双精度,约 15 位有效数字 | 8 字节 |
浮点数精度误差演示
当前数据状态:
CREATE TABLE precision_test (
id INT PRIMARY KEY,
f_val FLOAT,
d_val DOUBLE,
dec_val DECIMAL(20, 10)
);
INSERT INTO precision_test VALUES
(1, 0.1, 0.1, 0.1);
当前表数据:
| id | f_val | d_val | dec_val |
|---|---|---|---|
| 1 | 0.1 | 0.1 | 0.1000000000 |
操作语句:
SELECT
id,
f_val,
d_val,
dec_val,
f_val + 0.2 AS float_sum,
d_val + 0.2 AS double_sum,
dec_val + 0.2 AS decimal_sum
FROM precision_test;
操作后的数据状态:
| id | f_val | d_val | dec_val | float_sum | double_sum | decimal_sum |
|---|---|---|---|---|---|---|
| 1 | 0.1 | 0.1 | 0.1000000000 | 0.30000001 | 0.30000000000000004 | 0.3000000000 |
结果解读:
FLOAT的0.1 + 0.2产生了明显误差0.30000001DOUBLE的误差更小但仍有0.30000000000000004DECIMAL精确得到0.3000000000- 浮点数在计算机中以二进制近似存储,无法精确表示某些十进制小数(如 0.1)
- 金额计算必须使用
DECIMAL,绝不能用FLOAT或DOUBLE
关键警告:
FLOAT(10,2)存储的金额10.2减去10.1可能不是精确的0.1。金额计算务必用DECIMAL。
常见误区
| 误区 | 正解 |
|---|---|
INT(11) 比 INT(10) 存储范围大 | 显示宽度不影响存储,两者范围完全相同。 |
金额用 FLOAT 或 DOUBLE | 浮点数有精度误差,金额必须用 DECIMAL。 |
UNSIGNED 只是不允许负数 | 同时使正数范围翻倍,如 INT UNSIGNED 最大 42 亿。 |
| 数值类型越大约好 | 更大的类型占用更多存储和内存,影响索引效率和缓存命中率。 |
面试考点
Q:DECIMAL 和 FLOAT 的区别?
DECIMAL是定点数,以字符串形式存储,无精度损失,适合金额;FLOAT是浮点数,二进制近似存储,有精度误差,适合科学计算。
Q:MySQL 有没有布尔类型?
没有。
BOOL和BOOLEAN是TINYINT(1)的同义词。0 表示假,非 0 表示真。
Q:INT(10) 和 INT(11) 有什么区别?
没有本质区别。括号中的数字是显示宽度提示,仅当配合
ZEROFILL时影响输出格式(如INT(5) ZEROFILL存储 123 显示为 00123)。
小结
- 整数类型按范围选择,常规主键用
INT UNSIGNED,大 ID 用BIGINT INT(M)的M只是显示宽度,不影响存储- 金额必须用
DECIMAL,绝不能用FLOAT/DOUBLE - 浮点数只用于对精度不敏感的科学计算场景
下一章引子:数值之外,数据库中存储更多的是文本——姓名、地址、描述信息。字符串类型的选择同样关键。