SQL Server存储过程加密后仍可被反编译,WITH ENCRYPTION仅隐藏sys.sql_modules.definition内容,不提供强加密保护,专业工具可恢复原始文本,且无法阻止调用、调试或权限检查。

SQL Server存储过程加密后还能被反编译吗
不能真正防止逆向,WITH ENCRYPTION 仅隐藏 sp_helptext 和 SSMS 中的定义,不改变执行逻辑或数据访问权限。它本质是把 sys.sql_modules.definition 字段设为 NULL,而非强加密——专业工具(如 DACPAC 提取、内存 dump 或第三方解密器)仍可能恢复原始文本。
常见错误现象:sp_helptext 'proc_name' 返回“对象没有定义”,但 EXEC proc_name 正常运行;SSMS 刷新存储过程时显示“加密对象”,右键“修改”报错。
- 加密不阻止调用、调试、审计或权限检查
- 无法加密已存在的存储过程,必须
DROP后重建 - 加密后无法直接修改,必须先
DROP再CREATE(无 ALTER ENCRYPTION 语法)
WITH ENCRYPTION 必须和 CREATE/ALTER 一起用
WITH ENCRYPTION 不是独立命令,只能作为 CREATE PROCEDURE 或 ALTER PROCEDURE 的可选子句出现。单独执行 ALTER PROCEDURE ... WITH ENCRYPTION 会报错 Incorrect syntax near the keyword 'WITH',因为缺少完整定义体。
正确写法示例:
CREATE PROCEDURE dbo.GetUserInfo
@UserId INT
WITH ENCRYPTION
AS
BEGIN
SELECT Name, Email FROM Users WHERE Id = @UserId;
END
- 必须在
AS关键字之前声明WITH ENCRYPTION -
ENCRYPTION不区分大小写,但建议全大写保持一致性 - 若同时使用
RECOMPILE或EXECUTE AS,WITH ENCRYPTION要放在最前面
加密后如何安全维护源码
一旦加密,原始 SQL 就从系统视图中消失,sys.sql_modules 的 definition 列为 NULL。这意味着你无法靠数据库本身找回代码——必须依赖外部备份。
实际运维中容易踩的坑:
- 没在版本控制系统(Git)里存一份未加密的
.sql文件,导致紧急修复时只能靠记忆重写 - 误删本地脚本又没做 DACPAC 导出,加密后等于永久丢失逻辑
- 用 SSMS “生成脚本”功能导出加密对象,结果只得到空的
CREATE PROCEDURE ... WITH ENCRYPTION AS BEGIN END
建议做法:所有带 WITH ENCRYPTION 的存储过程,都配套提交未加密源码到 Git,并在部署脚本中显式加上该子句。
加密对性能和兼容性有影响吗
没有。SQL Server 在首次执行时编译并缓存执行计划,WITH ENCRYPTION 不参与编译流程,也不改变查询优化器行为。它只作用于元数据层的文本存储方式。
但要注意两点:
- SQL Server 2005 及以后全部支持,但 Azure SQL Database 兼容性级别低于 120 时可能不识别该子句(建议设为 140+)
- 某些 ORM 工具(如 Entity Framework 的 Database-First)读取存储过程时会跳过加密对象,因
sys.dm_exec_describe_first_result_set无法获取参数信息 - Always Encrypted 或 TDE 等其他加密机制与
WITH ENCRYPTION无关,不叠加生效
真正需要保护逻辑时,应优先考虑权限控制(如 DENY VIEW DEFINITION)、应用层封装或服务化隔离,而不是依赖这个形同虚设的开关。

















