mysql中select直接脱敏的常见写法是用concat(substring(phone,1,3),'**',substring(phone,8,4)),需注意null、字符串长度不足及非数字字符问题,推荐配合正则校验与trim使用。

SELECT 中直接对字段做脱敏处理的常见写法
多数场景下,你不需要先查原值再用应用层脱敏——SQL 层就能边查边脱敏。关键是选对函数、注意 NULL 和长度边界。
以手机号为例,常见脱敏是保留前3位和后4位,中间用 * 替代。不同数据库语法略有差异:
- MySQL:用
CONCAT+SUBSTRING,注意SUBSTRING(phone, 1, 3)从 1 开始计数(不是 0) - PostgreSQL:用
LEFT/RIGHT或SUBSTRING,SUBSTRING(phone FROM 1 FOR 3)更清晰 - SQL Server:用
LEFT+RIGHT,但要注意LEN对 NULL 返回 NULL,需套ISNULL
示例(MySQL):
SELECT phone AS original_phone, CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) AS masked_phone FROM users;
处理 NULL 或格式不规范的数据时容易出错
脱敏逻辑一旦遇到空值、短字符串(如 '123')、含空格或分隔符的字段,就可能报错或输出异常结果。
- MySQL 的
SUBSTRING超出长度会静默返回空字符串,看似安全,但RIGHT('123', 4)返回'123',导致脱敏不完整 - 建议加长度校验:用
CASE WHEN LENGTH(phone) = 11 THEN ... ELSE phone END - 更稳妥的做法是先用
TRIM清空两端空格,再用正则(如 MySQL 8.0+ 的REGEXP_REPLACE)过滤非数字字符
示例(带校验):
SELECT phone, CASE WHEN phone REGEXP '^1[3-9]\d{9}$' THEN CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) ELSE 'INVALID' END AS masked_phone FROM users;
在视图或报表 SQL 中同时输出原值与脱敏值的注意事项
如果这个 SELECT 是给 BI 工具或下游系统用的,要特别注意权限和缓存问题。
- 别把脱敏逻辑写进应用代码里再拼字段——既重复又难审计;SQL 层统一输出最可控
- 某些 BI 工具(如 Tableau、Superset)会缓存查询结果,若脱敏逻辑依赖会话变量或当前用户角色,必须显式声明为非确定性(例如 PostgreSQL 加
VOLATILE函数) - 如果表数据量大,脱敏表达式本身不走索引,但不会拖慢查询——它只在结果集生成阶段计算,不影响 WHERE 或 JOIN 的执行计划
Oracle 和 Hive 中脱敏写法的典型差异
Oracle 没有 LEFT/RIGHT,得靠 SUBSTR;Hive 默认不支持正则替换数字,且字符串索引从 1 开始但函数名大小写敏感。
- Oracle:
SUBSTR(phone, 1, 3) || '****' || SUBSTR(phone, -4)—— 注意负数索引表示从末尾往前数 - Hive:
CONCAT(SUBSTR(phone, 1, 3), '****', SUBSTR(phone, LENGTH(phone)-3, 4)),且必须确保字段是STRING类型,INT会隐式转为空字符串 - Hive 3.1+ 支持
REGEXP_REPLACE(phone, '(\d{3})\d{4}(\d{4})', '$1****$2'),但性能比纯 SUBSTR 差不少
真正麻烦的是跨平台迁移:同一份报表 SQL 在 Hive 跑通,到 Oracle 可能因索引偏移或 NULL 处理方式不同而漏脱敏。











