MySQL 浮点数、定点数与位类型:搞懂 3 类特殊数值的核心用法
MySQL 浮点数、定点数与位类型:搞懂 3 类特殊数值的核心用法
在 MySQL 中,除了常用的整型和字符串,浮点数、定点数与位类型虽不天天用,但在特定场景(如金额、状态存储)中至关重要。很多人会混淆浮点数和定点数的 “精度差异”,对位类型的 “空间优势” 也不熟悉 —— 今天就聚焦核心,用通俗语言讲清这 3 类类型的 “怎么用、选哪个”。
一、浮点数(FLOAT/Double):近似值,适合非精确场景
浮点数的核心是 “存储近似值”,优点是存储效率高、计算快,缺点是可能有精度损失,适合不需要绝对精确的场景(如温度、体重、科学计算)。
1. 核心特性:精度是 “约数”,不是 “精确值”
MySQL 的浮点数分两种,核心区别在精度和存储大小:
类型 | 存储字节 | 大致精度(有效数字) | 核心场景 |
---|---|---|---|
FLOAT | 4 字节 | 6~7 位 | 精度要求低(如温度 23.5℃) |
DOUBLE | 8 字节 | 15~17 位 | 精度要求中等(如 GPS 坐标) |
⚠️ 关键提醒:浮点数的 “精度” 是 “有效数字位数”,不是 “小数位数”。比如FLOAT(5,2)表示总有效数字 5 位,小数位 2 位(范围:-999.99 ~ 999.99),但存储的是近似值,可能有误差。
2. 基本用法:注意精度设置与误差
-- 示例1:存储温度(精度要求低,用FLOAT)
CREATE TABLE weather (temp FLOAT(5,2) -- 总5位,小数2位(如25.36℃)
);INSERT INTO weather (temp) VALUES (25.36), (18.92);
SELECT * FROM weather; -- 正常显示,但内部是近似存储-- 示例2:浮点数的精度损失坑(必看!)
CREATE TABLE test_float (num FLOAT(10,2)
);
INSERT INTO test_float (num) VALUES (0.1), (0.2);
SELECT num, num+0.1 FROM test_float; -- 0.1+0.1可能显示0.20,但0.1+0.2可能≠0.30!
3. 适用场景:绝对不存金额!
-
✅ 推荐:温度、湿度、压力等物理量,GPS 坐标、模糊评分(如 4.5 星)。
-
❌ 禁止:货币(如 19.99 元)、订单金额、税费等需精确计算的场景(精度损失会导致对账错误)。
二、定点数(DECIMAL):精确值,专为金额而生
定点数的核心是 “存储精确值”,通过 “整数 + 小数分离存储” 避免精度损失,是金融、电商场景的 “标配”,唯一缺点是存储和计算比浮点数稍慢(可忽略)。
1. 核心特性:精度完全可控,无误差
DECIMAL 的精度由M(总位数)和D(小数位数)定义,格式为DECIMAL(M,D),比如DECIMAL(10,2)表示 “总 10 位数字,其中小数 2 位”(范围:-99999999.99 ~ 99999999.99)。
关键参数 | 含义 | 限制 |
---|---|---|
M | 总有效数字(整数 + 小数) | 1~65(默认 10) |
D | 小数位数 | 0~30(默认 0,且 D≤M) |
2. 基本用法:金额场景的标准写法
-- 示例1:存储订单金额(精确到分,必用DECIMAL)
CREATE TABLE orders (order_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,amount DECIMAL(10,2), -- 最大99999999.99元(足够大多数业务)tax DECIMAL(8,2) -- 税费,8位总位数(最大999999.99)
);-- 插入与计算:无精度损失
INSERT INTO orders (amount, tax) VALUES (199.99, 19.99);
SELECT amount + tax AS total FROM orders; -- 结果精确为219.98,不会错
3. 适用场景:只要涉及 “钱”,就用 DECIMAL
-
✅ 推荐:订单金额、用户余额、税费、汇率等需精确到分 / 厘的场景。
-
❌ 不推荐:非精确计算(如温度)—— 没必要,浪费存储(DECIMAL 比 FLOAT 占字节多)。
三、位类型(BIT):二进制存储,省空间的 “状态容器”
位类型(BIT)是 “二进制数据类型”,直接存储 0/1 组成的二进制数,核心优势是 “极致省空间”—— 比如存 8 个开关状态,用 1 个 BIT (8) 就够(1 字节),而用 8 个 TINYINT 要 8 字节。
1. 核心特性:按 “位” 存储,支持位运算
类型 | 存储规则 | 范围 | 核心场景 |
---|---|---|---|
BIT(n) | n 为位数(1≤n≤64),占 1~8 字节 | 0 ~ 2ⁿ-1 | 多状态存储(如开关、权限) |
-
比如BIT(3)可存 3 个二进制位,能表示 0(000)~7(111),对应 8 种状态,仅占 1 字节。
-
支持位运算(&、|、~ 等),可快速判断某一位的状态(如 “是否开启推送”)。
2. 基本用法:存多状态,用位运算查询
-- 示例1:存储用户通知设置(3个状态,用BIT(3))
-- 位定义:第1位=短信通知(1=开,0=关),第2位=邮件通知,第3位=APP通知
CREATE TABLE user_settings (user_id INT UNSIGNED PRIMARY KEY,notify BIT(3) DEFAULT b'000' -- 默认全关,二进制值用b'xxx'表示
);-- 插入数据:用户1开启短信(第1位1)和APP通知(第3位1)→ 二进制101(即5)
INSERT INTO user_settings (user_id, notify) VALUES (1, b'101');-- 查询:判断用户1是否开启邮件通知(第2位是否为1)
-- 位运算:notify & b'010' → 若结果≠0,说明第2位是1
SELECT user_id, (notify & b'001') <> 0 AS sms_on, -- 短信是否开(notify & b'010') <> 0 AS email_on -- 邮件是否开
FROM user_settings WHERE user_id = 1;
3. 注意事项:查询需转换,避免直观性差
-
直接查询 BIT 字段会返回二进制值(如b’101’),需用BIN()函数转成字符串(如BIN(notify)返回 ‘101’),或用位运算判断。
-
适合存储 “不常修改、状态数量少” 的场景(如权限位),不适合状态多且常修改的场景(维护成本高)。
四、核心对比:3 类类型怎么选?
类型 | 精度 | 存储效率 | 适合场景 | 避坑点 |
---|---|---|---|---|
浮点数 | 近似 | 高 | 温度、GPS、非精确计算 | 绝对不能存金额 |
定点数 | 精确 | 中 | 金额、税费、精确小数 | 需合理设置 M 和 D(如金额用 10,2) |
位类型 | 无(二进制) | 极高 | 多状态、开关、权限 | 查询需用位运算或转换 |
五、总结:3 个核心原则,避免 90% 的错
-
金额用 DECIMAL:只要涉及钱,别犹豫,DECIMAL(10,2)(元 + 分)或DECIMAL(12,4)(元 + 厘)足够。
-
非精确用 FLOAT/DOUBLE:温度、坐标等场景,选 FLOAT(精度低)或 DOUBLE(精度高),省空间。
-
多状态用 BIT:存多个开关(如 3 个以上),用 BIT (n) 比多个 TINYINT 更省空间,配合位运算查询更高效。
搞懂这 3 类类型的 “核心差异” 和 “适用场景”,不用记复杂的参数细节,也能在实际开发中选对、用好 —— 这才是高效学习的关键。