You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Always Encrypted SQL Server存储过程出现TDS协议错误的原因

问题

从启用Always Encrypted的SQL Server数据库调用存储过程时,遇到以下错误:

SQLServerException: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 1 (""): Data type 0xC0 is unknown.

相关代码与配置

表和存储过程创建语句

CREATE TABLE [dbo].[test_table] (
    [id] [int] IDENTITY(1,1) NOT NULL,
    [encrypted_col] [nvarchar](255) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [MY_KEY], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL
)
GO

CREATE PROCEDURE [dbo].[test_sp]
    @test_param nvarchar(255)
AS
    SELECT * from test_table where encrypted_col = @test_param
GO

Java调用代码

try(CallableStatement callableStatement = connection.prepareCall("{call test_sp(?)}")) {
    callableStatement.setNString(1, "TEST VALUE");
    ResultSet rs = callableStatement.executeQuery(); // <-- 抛出异常
}

数据库连接URL

jdbc:sqlserver://localhost:1433;applicationName=MY-APP;databaseName=test_encryption;sendStringParametersAsUnicode=false;encrypt=true;trustServerCertificate=true;columnEncryptionSetting=enabled;enclaveAttestationUrl=http://localhost/Attestation;enclaveAttestationProtocol=HGS;

备注

  • 使用SQL Server 2019和最新版mssql驱动(12.6),二者兼容,降级驱动后问题依旧。
  • Hibernate读写数据库表正常,连接URL和加密密钥配置正确,仅调用存储过程时出错。
  • 存储过程可在SQL Server Management Studio中成功调用,数据库层面的存储过程和加密配置正确。
  • 尝试多种调用存储过程的方式(Hibernate Query、Spring Jpa Query),均出现相同错误。
  • 创建未加密的数据库表时,调用存储过程可正常工作。
  • 已尝试将sendStringParametersAsUnicode设为true和false,问题依旧。
原因分析与解决方案

核心原因

错误的根源是存储过程的参数未指定与加密列匹配的排序规则:

  • 加密列encrypted_col使用了Latin1_General_BIN2排序规则,但存储过程参数@test_param仅定义为nvarchar(255),未同步指定该排序规则。
  • JDBC驱动在处理Always Encrypted加密列的存储过程调用时,对参数元数据的要求远高于SSMS:必须确保参数的数据类型、排序规则与加密列完全一致,否则会导致TDS协议层面的数据类型识别错误(0xC0是SQL Server内部标识带特定排序规则的Unicode字符串的类型码,但驱动无法正确解析)。

解决方案

修改存储过程,为参数添加与加密列一致的排序规则,重新编译后即可解决问题:

CREATE PROCEDURE [dbo].[test_sp]
    @test_param nvarchar(255) COLLATE Latin1_General_BIN2
AS
    SELECT * from test_table where encrypted_col = @test_param
GO

逻辑验证

  • 直接读写表时,JDBC驱动能从表结构中直接获取列的完整元数据(包括排序规则),自动匹配参数,因此Hibernate操作表正常。
  • 未加密列对排序规则的匹配要求较低,因此未加密表的存储过程能正常运行。

内容的提问来源于stack exchange,提问作者Alexandru Severin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:02:28