@@ -187,6 +187,37 @@ TIMESTAMP 只需要使用 4 个字节的存储空间,但是 DATETIME 需要耗
187
187
188
188
MySQL 中没有专门的布尔类型,而是用 TINYINT(1) 类型来表示布尔值。TINYINT(1) 类型可以存储 0 或 1,分别对应 false 或 true。
189
189
190
+ ### 手机号存储用 INT 还是 VARCHAR?
191
+
192
+ 存储手机号,** 强烈推荐使用 VARCHAR 类型** ,而不是 INT 或 BIGINT。主要原因如下:
193
+
194
+ 1 . ** 格式兼容性与完整性:**
195
+ - 手机号可能包含前导零(如某些地区的固话区号)、国家代码前缀('+'),甚至可能带有分隔符('-' 或空格)。INT 或 BIGINT 这种数字类型会自动丢失这些重要的格式信息(比如前导零会被去掉,'+' 和 '-' 无法存储)。
196
+ - VARCHAR 可以原样存储各种格式的号码,无论是国内的 11 位手机号,还是带有国家代码的国际号码,都能完美兼容。
197
+ 2 . ** 非算术性:** 手机号虽然看起来是数字,但我们从不对它进行数学运算(比如求和、平均值)。它本质上是一个标识符,更像是一个字符串。用 VARCHAR 更符合其数据性质。
198
+ 3 . ** 查询灵活性:**
199
+ - 业务中常常需要根据号段(前缀)进行查询,例如查找所有 "138" 开头的用户。使用 VARCHAR 类型配合 ` LIKE '138%' ` 这样的 SQL 查询既直观又高效。
200
+ - 如果使用数字类型,进行类似的前缀匹配通常需要复杂的函数转换(如 CAST 或 SUBSTRING),或者使用范围查询(如 ` WHERE phone >= 13800000000 AND phone < 13900000000 ` ),这不仅写法繁琐,而且可能无法有效利用索引,导致性能下降。
201
+ 4 . ** 加密存储的要求(非常关键):**
202
+ - 出于数据安全和隐私合规的要求,手机号这类敏感个人信息通常必须加密存储在数据库中。
203
+ - 加密后的数据(密文)是一长串字符串(通常由字母、数字、符号组成,或经过 Base64/Hex 编码),INT 或 BIGINT 类型根本无法存储这种密文。只有 VARCHAR、TEXT 或 BLOB 等类型可以。
204
+
205
+ ** 关于 VARCHAR 长度的选择:**
206
+
207
+ - ** 如果不加密存储(强烈不推荐!):** 考虑到国际号码和可能的格式符,VARCHAR(20) 到 VARCHAR(32) 通常是一个比较安全的范围,足以覆盖全球绝大多数手机号格式。VARCHAR(15) 可能对某些带国家码和格式符的号码来说不够用。
208
+ - ** 如果进行加密存储(推荐的标准做法):** 长度必须根据所选加密算法产生的密文最大长度,以及可能的编码方式(如 Base64 会使长度增加约 1/3)来精确计算和设定。通常会需要更长的 VARCHAR 长度,例如 VARCHAR(128), VARCHAR(256) 甚至更长。
209
+
210
+ 最后,来一张表格总结一下:
211
+
212
+ | 对比维度 | VARCHAR 类型(推荐) | INT/BIGINT 类型(不推荐) | 说明/备注 |
213
+ | ---------------- | --------------------------------- | ---------------------------- | --------------------------------------------------------------------------- |
214
+ | ** 格式兼容性** | ✔ 能存前导零、"+"、"-"、空格等 | ✘ 自动丢失前导零,不能存符号 | VARCHAR 能原样存储各种手机号格式,INT/BIGINT 只支持单纯数字,且前导零会消失 |
215
+ | ** 完整性** | ✔ 不丢失任何格式信息 | ✘ 丢失格式信息 | 例如 "013800012345" 存进 INT 会变成 13800012345,"+" 也无法存储 |
216
+ | ** 非算术性** | ✔ 适合存储“标识符” | ✘ 只适合做数值运算 | 手机号本质是字符串标识符,不做数学运算,VARCHAR 更贴合实际用途 |
217
+ | ** 查询灵活性** | ✔ 支持 ` LIKE '138%' ` 等 | ✘ 查询前缀不方便或性能差 | 使用 VARCHAR 可高效按号段/前缀查询,数字类型需转为字符串或其他复杂处理 |
218
+ | ** 加密存储支持** | ✔ 可存储加密密文(字母、符号等) | ✘ 无法存储密文 | 加密手机号后密文是字符串/二进制,只有 VARCHAR、TEXT、BLOB 等能兼容 |
219
+ | ** 长度设置建议** | 15~ 20(未加密),加密视情况而定 | 无意义 | 不加密时 VARCHAR(15~ 20) 通用,加密后长度取决于算法和编码方式 |
220
+
190
221
## MySQL 基础架构
191
222
192
223
> 建议配合 [ SQL 语句在 MySQL 中的执行过程] ( ./how-sql-executed-in-mysql.md ) 这篇文章来理解 MySQL 基础架构。另外,“一个 SQL 语句在 MySQL 中的执行流程”也是面试中比较常问的一个问题。
0 commit comments