已配置Always Encrypted,C++客户端插入数据遇加密方案不匹配错误求助
问题描述
已在服务器端为表列配置Always Encrypted,使用C++客户端时,通过以下连接字符串连接数据库:
CString connString = L"Driver={ODBC Driver 17 for SQL Server};Server=192.122.200.200,1433;Encrypt=no;Trusted_Connection=no;ColumnEncryption=Enabled;DATABASE=AlwaysEncrypted;UID=sa;PWD=;";
执行以下插入数据的命令时失败:
CString csQStrInsert = L"declare @val1 int = 3; declare @val2 int = 3; insert into [dbo].[Table_AlwaysEncrypted] ([col1], [col2]) values (@val1, @val2);"; pDatabase->ExecuteSQL(csQStrInsert);
报错信息:
pEX->m_strError = L"Encryption scheme mismatch for columns/variables '@val1'. The encryption scheme for the columns/variables is (encryption_type = 'PLAINTEXT') and the expression near line '1' expects it to be DETERMINISTIC, or PLAIN TEXT.
问题原因与解决方法
问题根源:你在SQL脚本里直接声明并赋值变量,这些变量是在服务器端以明文形式存在的。而Always Encrypted的核心逻辑是客户端加密——只有客户端能处理明文数据,服务器只能存储加密后的内容,无法直接接收明文变量插入加密列。
正确做法:使用参数化查询,不要在SQL语句里声明变量,而是把参数值传递给驱动,让ODBC驱动在客户端完成加密后再发送给服务器。示例代码如下:
// 准备参数化的插入语句 CString csQStrInsert = L"insert into [dbo].[Table_AlwaysEncrypted] ([col1], [col2]) values (?, ?);"; // 创建参数化命令对象(基于ODBC标准流程) SQLHSTMT hStmt; SQLAllocHandle(SQL_HANDLE_STMT, pDatabase->m_hdbc, &hStmt); SQLPrepare(hStmt, (SQLWCHAR*)csQStrInsert.GetString(), SQL_NTS); // 绑定参数1,值为3 int val1 = 3; SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val1, 0, NULL); // 绑定参数2,值为3 int val2 = 3; SQLBindParameter(hStmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &val2, 0, NULL); // 执行语句 SQLExecute(hStmt); // 释放资源 SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
这样驱动会自动识别目标列的加密配置,在客户端对参数值进行加密,再将密文发送到服务器,避免了服务器处理明文的情况,也就不会触发加密方案不匹配的错误。
内容的提问来源于stack exchange,提问作者Amal
相关产品推荐
相关产品推荐

