SQL Server代理作业结合Always Encrypted列执行报错求解决
这个错误我之前帮客户排查过好几次,本质是SQL Server代理的作业执行上下文没有和你手动在SSMS查询窗口里启用的Always Encrypted配置对齐。你手动执行时开启了Column Encryption Setting=enabled和Enable Parameterization for Always Encrypted,但代理作业默认不会继承这些设置,导致参数没有被自动加密,触发了加密方案不匹配的错误。
下面是具体的解决步骤:
1. 修改作业步骤的连接字符串,启用Column Encryption Setting
编辑你的SQL Server代理作业步骤:
- 打开作业步骤的“常规”选项卡,点击“连接”按钮(或“数据库”下拉框旁的“...”按钮)
- 在弹出的连接属性窗口中,切换到“额外连接参数”标签页
- 添加参数:
Column Encryption Setting=Enabled - 保存设置后重新执行作业
2. 确保执行作业的代理账户有密钥访问权限
SQL Server代理作业默认使用代理服务账户或你指定的自定义代理账户,这个账户需要:
- 能访问列主密钥(CMK)所在的密钥存储(比如本地证书存储、Azure Key Vault)
- 对数据库中的列加密密钥(CEK)拥有
VIEW DEFINITION权限
可以用以下SQL语句给代理账户授予CEK权限:
GRANT VIEW DEFINITION ON COLUMN_ENCRYPTION_KEY::CEK_Auto1 TO [YourProxyAccount];
3. 启用Always Encrypted的参数化支持(关键)
你手动执行时开启的Enable Parameterization for Always Encrypted会让客户端驱动自动加密存储过程参数,但SQL Server代理的TSQL作业步骤默认不会启用这个设置,推荐两种解决办法:
方法A:改用PowerShell作业步骤
创建PowerShell类型的作业步骤,使用SqlServer模块的Invoke-SqlCmd命令,明确启用加密和参数化:
Invoke-SqlCmd -ServerInstance "YourServerName" -Database "MyDatabase" -Query "EXEC TestStoredProcedure @name = 'TestValue'" -ColumnEncryptionSetting Enabled -EnableAlwaysEncryptedParameterization
方法B:验证存储过程参数匹配性
确保存储过程的参数类型和加密列完全一致(比如加密列是nvarchar(50),参数也需定义为nvarchar(50)),避免因类型不匹配导致加密逻辑失效。
错误33299的核心逻辑:手动执行时,SSMS客户端驱动会自动加密
@name参数,符合存储过程期望的加密方案;但代理作业执行时,参数以明文传递,数据库检测到明文参数与加密列的要求不匹配,因此抛出该错误。
内容的提问来源于stack exchange,提问作者Sruthy John

