WITH ENCRYPTION并非真正加密,仅是SQL Server内部混淆并清空sys.sql_modules.definition字段,防普通用户查看;DBA、DAC连接、执行计划缓存等仍可还原明文,且加密后无法ALTER,必须DROP重建,维护依赖外部源码备份。

SQL Server 的 WITH ENCRYPTION 不是加密,只是让普通用户查不到源码;DBA、备份文件、执行计划缓存里都能还原明文,线上误删后还无法用 ALTER PROCEDURE 修改。
为什么 WITH ENCRYPTION 不能叫“加密”
它不使用 AES 或 RSA 等标准算法,只是把 T-SQL 文本用 SQL Server 内部动态密钥做一次混淆,写入 sys.sql_modules.definition 时设为 NULL 或乱码。效果仅限于屏蔽以下两种常规查看方式:
-
sp_helptext your_proc_name返回空或报错 -
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('your_proc')返回NULL
但只要拥有 VIEW SERVER STATE 权限,就能从 sys.dm_exec_query_plan 提取刚执行过的原始文本;启用 DAC 连接后,甚至能直接读内存页里的解密后代码。
加密后怎么安全维护和修改
一旦加了 WITH ENCRYPTION,就彻底失去在线编辑能力:ALTER PROCEDURE 会报错,必须先 DROP 再 CREATE。这带来三个高危操作点:
- 没在 Git 里存未加密的 .sql 源文件,紧急修复时只能靠记忆重写逻辑
- SSMS “生成脚本”导出的是空壳:
CREATE PROCEDURE ... WITH ENCRYPTION AS BEGIN END - 误删本地脚本 + 没导出 DACPAC,等于永久丢失源码
建议做法:所有带 WITH ENCRYPTION 的过程,都配套提交未加密源码到 Git,并在部署脚本中显式加上该子句——不是为了“防泄露”,而是为了“别丢活儿”。
真正该防谁?别防错对象
如果你的目标是满足等保三级或应对内部 DBA 审计,WITH ENCRYPTION 毫无意义。它唯一有效场景是防止开发同事顺手查生产环境的计费规则、脱敏逻辑这类非核心但需隔离的内容。
- 硬编码在过程里的密钥或密码,加密后反而更难被代码扫描工具发现
- 想防备份泄露?TDE(透明数据加密)才管数据库文件层,
WITH ENCRYPTION对备份完全无效 - 想防执行时敏感数据暴露?该用
ALWAYS ENCRYPTED+ 客户端驱动,而不是折腾过程体
最常被忽略的一点:加了 WITH ENCRYPTION 后,连你自己都看不到定义了——但你忘了权限控制比“看不见”更重要:限制谁有 VIEW DEFINITION、谁可连 DAC、谁能看到备份文件,这些才是实际防线。











