在SQL Server日常开发中,经常遇到这样的需求:表里有用户的手机号、身份证号等敏感信息,但对外提供的查询接口或报表不能展示明文。利用嵌套查询,也就是把一个查询作为另一个查询的数据源,可以在逻辑层做替换,实现数据脱敏。下面先看一个基础示例。

什么是嵌套查询脱敏
嵌套查询是指在一个 SELECT 语句的 FROM 子句或 WHERE 子句中嵌入另一个 SELECT 语句。数据脱敏的逻辑替换子查询,通常是把原表先查出来作为一个派生表,再在外层查询中对敏感列使用 CASE 或字符串函数进行掩盖。
基本结构
- 内层查询:选出原始数据,可附带必要的过滤条件
- 外层查询:对敏感字段做掩码处理,如只保留前三位和后四位
逻辑替换子查询示例
假设有一张客户表 Customer,包含 Id、Name、Phone 三列,Phone 是手机号。我们希望查询时只显示前三位和后两位,中间用星号代替。
SELECT
Id,
Name,
CASE
WHEN LEN(Phone) = 11 THEN
LEFT(Phone, 3) + '****' + RIGHT(Phone, 2)
ELSE
'******'
END AS PhoneMasked
FROM (
SELECT Id, Name, Phone
FROM Customer
WHERE IsDeleted = 0
) AS sub
上面的代码中,内层子查询 sub 负责取出未删除的客户数据,外层查询通过 CASE 和字符串函数完成逻辑替换,实现脱敏。
利用函数封装脱敏逻辑
如果多处都需要脱敏,可以把替换逻辑写成内联函数,再在嵌套查询里调用,保持语句清晰。
CREATE FUNCTION dbo.MaskPhone(@phone VARCHAR(20))
RETURNS VARCHAR(20)
AS
BEGIN
IF LEN(@phone) = 11
RETURN LEFT(@phone, 3) + '****' + RIGHT(@phone, 2)
RETURN '******'
END
之后在嵌套查询中直接使用函数:
SELECT
Id,
dbo.MaskPhone(Phone) AS PhoneMasked
FROM (
SELECT Id, Phone
FROM Customer
) AS sub
在 WHERE 中使用脱敏子查询
有时需要根据脱敏后的值做过滤,这时可以把逻辑替换子查询放在 WHERE 的 EXISTS 中,或者将派生表与条件结合。
| 场景 | 做法 |
|---|---|
| 按掩码后手机查 | 外层对 sub.Phone 做掩码再比较 |
| 排除特定明文 | 内层先排除,外层再脱敏 |
示例:过滤特定号段
SELECT Id, Name,
LEFT(Phone, 3) + '****' + RIGHT(Phone, 2) AS PhoneMasked
FROM (
SELECT Id, Name, Phone
FROM Customer
WHERE Phone NOT LIKE '123%'
) AS sub
注意事项
使用嵌套查询脱敏时,原始数据仍在数据库内,只是输出被替换,因此数据库权限管理依然重要。另外,若脱敏逻辑复杂,建议放在视图里,业务直接查视图即可。
嵌套查询脱敏是一种轻量方案,不改表结构,只在查询层做逻辑替换,适合大多数读场景。
通过上述方式,开发者可以在 SQL Server 中利用嵌套查询稳定地完成数据脱敏,既满足安全合规,也保持查询灵活。
SQL_Server嵌套查询数据脱敏修改时间:2026-07-28 18:42:12