varchar 与使用 (encryption_type = 'DETERMINISTIC' 加密的 varchar(50) 不兼容
varchar is incompatible with varchar(50) encrypted with (encryption_type = 'DETERMINISTIC'
我正在尝试从我的应用程序传入一个参数以在存储过程中进行搜索。我这样传入参数:
SqlParameter param1 = new SqlParameter(@"@FilterCustomerPO", "G06756");
param1.DbType = DbType.AnsiString;
param1.Direction = ParameterDirection.Input;
param1.Size = 50;
sqlCmd.Parameters.Add(param1);
在存储过程中,是这样定义的:
ALTER PROCEDURE [dbo].[usp_POListing]
@FilterCustomerPO VARCHAR (50)
AS
BEGIN
SELECT *
FROM [Order]
WHERE PONumber = @FilterCustomerPO
END
PONumber
列使用 DETERMINISTIC
加密类型加密。
当我传入一个值时,出现错误:
Operand type clash: varchar is incompatible with varchar(50) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'ColumnEncryptionKey', column_encryption_key_database_name = 'DataPortal') collation_name = 'SQL_Latin1_General_CP1_CI_AS'
我看到很多其他人对此进行了报告,但是 none 这些解决方案对我有用。如您所见,我正在使用参数化查询,所以不确定我可能遗漏了什么。
编辑:
我也试过以这种方式传递参数 - 同样的错误:
sqlCmd.Parameters.Add("FilterCustomerPO", SqlDbType.VarChar, 50);
sqlCmd.Parameters["FilterCustomerPO"].Value = "G06756"
订单Table的定义如下:
CREATE TABLE [dbo].[Order]
(
[OrderID] [INT] IDENTITY(1,1) NOT NULL,
[CustomerID] [INT] NOT NULL,
[OrderNumber] [INT] NOT NULL,
[DBCOrderNumber] [VARCHAR](25) NOT NULL,
[PONumber] [VARCHAR](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [ColumnEncryptionKey], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,
[BillingName] [VARCHAR](255) NOT NULL,
CONSTRAINT [PK_Order]
PRIMARY KEY CLUSTERED ([OrderID] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
我的客户端连接字符串还包括 Column Encryption Setting=Enabled
请注意:我能够很好地检索数据。当我将参数发送到查询中,并在收到错误时尝试执行 comparison/filter。
这是AlwaysEncrypted, which only uses client-side encryption keys. It's designed to prevent SQL Server (or its administrators) from being able to decrypt the data. If you want column encryption with server-managed keys, SQL Server has that too, but it's a different feature. See Encrypt a Column of Data。
在 AlwaysEncrypted 中 Order.PONumber 的数据类型实际上并不只是 varchar(50)
。这是
[varchar](50) COLLATE Latin1_General_BIN2
ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = [ColumnEncryptionKey],
ENCRYPTION_TYPE = Deterministic,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256')
这是列类型的 all 部分,因此您不能使用 varchar(50)
类型的参数。要搜索此列,客户端必须使用指定的密钥和算法加密参数值,因此 SQL 服务器可以将确定性加密的列值与加密的参数值匹配。 SQL 服务器没有列加密密钥,因此无法解密列值或加密参数值。
SQL 服务器具有将加密的 table 参数传播到存储过程或函数的能力。这个似乎工作正常。要检查存储过程参数是否已选取列加密,请检查 sys.parameters。 EG
select name, encryption_type_desc, encryption_algorithm_name
from sys.parameters
where object_id = object_id('usp_POListing')
我创建了一个简单的重现并且能够像这样调用存储过程:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp27
{
class Program
{
static void Main(string[] args)
{
using (var con = new SqlConnection("server=localhost;database=testdb;integrated security=true;Column Encryption Setting=enabled"))
{
con.Open();
var sqlCmd = new SqlCommand("usp_POListing", con);
sqlCmd.CommandType = CommandType.StoredProcedure;
var param1 = new SqlParameter("@FilterCustomerPO", "G06756");
param1.SqlDbType = SqlDbType.VarChar;
param1.Size = 50;
param1.Direction = ParameterDirection.Input;
sqlCmd.Parameters.Add(param1);
var dt = new DataTable();
using (var rdr = sqlCmd.ExecuteReader())
{
dt.Load(rdr);
}
}
}
}
}
一般见Develop using Always Encrypted with .NET Framework Data Provider
我正在尝试从我的应用程序传入一个参数以在存储过程中进行搜索。我这样传入参数:
SqlParameter param1 = new SqlParameter(@"@FilterCustomerPO", "G06756");
param1.DbType = DbType.AnsiString;
param1.Direction = ParameterDirection.Input;
param1.Size = 50;
sqlCmd.Parameters.Add(param1);
在存储过程中,是这样定义的:
ALTER PROCEDURE [dbo].[usp_POListing]
@FilterCustomerPO VARCHAR (50)
AS
BEGIN
SELECT *
FROM [Order]
WHERE PONumber = @FilterCustomerPO
END
PONumber
列使用 DETERMINISTIC
加密类型加密。
当我传入一个值时,出现错误:
Operand type clash: varchar is incompatible with varchar(50) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'ColumnEncryptionKey', column_encryption_key_database_name = 'DataPortal') collation_name = 'SQL_Latin1_General_CP1_CI_AS'
我看到很多其他人对此进行了报告,但是 none 这些解决方案对我有用。如您所见,我正在使用参数化查询,所以不确定我可能遗漏了什么。
编辑:
我也试过以这种方式传递参数 - 同样的错误:
sqlCmd.Parameters.Add("FilterCustomerPO", SqlDbType.VarChar, 50);
sqlCmd.Parameters["FilterCustomerPO"].Value = "G06756"
订单Table的定义如下:
CREATE TABLE [dbo].[Order]
(
[OrderID] [INT] IDENTITY(1,1) NOT NULL,
[CustomerID] [INT] NOT NULL,
[OrderNumber] [INT] NOT NULL,
[DBCOrderNumber] [VARCHAR](25) NOT NULL,
[PONumber] [VARCHAR](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [ColumnEncryptionKey], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,
[BillingName] [VARCHAR](255) NOT NULL,
CONSTRAINT [PK_Order]
PRIMARY KEY CLUSTERED ([OrderID] ASC)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
我的客户端连接字符串还包括 Column Encryption Setting=Enabled
请注意:我能够很好地检索数据。当我将参数发送到查询中,并在收到错误时尝试执行 comparison/filter。
这是AlwaysEncrypted, which only uses client-side encryption keys. It's designed to prevent SQL Server (or its administrators) from being able to decrypt the data. If you want column encryption with server-managed keys, SQL Server has that too, but it's a different feature. See Encrypt a Column of Data。
在 AlwaysEncrypted 中 Order.PONumber 的数据类型实际上并不只是 varchar(50)
。这是
[varchar](50) COLLATE Latin1_General_BIN2
ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = [ColumnEncryptionKey],
ENCRYPTION_TYPE = Deterministic,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256')
这是列类型的 all 部分,因此您不能使用 varchar(50)
类型的参数。要搜索此列,客户端必须使用指定的密钥和算法加密参数值,因此 SQL 服务器可以将确定性加密的列值与加密的参数值匹配。 SQL 服务器没有列加密密钥,因此无法解密列值或加密参数值。
SQL 服务器具有将加密的 table 参数传播到存储过程或函数的能力。这个似乎工作正常。要检查存储过程参数是否已选取列加密,请检查 sys.parameters。 EG
select name, encryption_type_desc, encryption_algorithm_name
from sys.parameters
where object_id = object_id('usp_POListing')
我创建了一个简单的重现并且能够像这样调用存储过程:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp27
{
class Program
{
static void Main(string[] args)
{
using (var con = new SqlConnection("server=localhost;database=testdb;integrated security=true;Column Encryption Setting=enabled"))
{
con.Open();
var sqlCmd = new SqlCommand("usp_POListing", con);
sqlCmd.CommandType = CommandType.StoredProcedure;
var param1 = new SqlParameter("@FilterCustomerPO", "G06756");
param1.SqlDbType = SqlDbType.VarChar;
param1.Size = 50;
param1.Direction = ParameterDirection.Input;
sqlCmd.Parameters.Add(param1);
var dt = new DataTable();
using (var rdr = sqlCmd.ExecuteReader())
{
dt.Load(rdr);
}
}
}
}
}
一般见Develop using Always Encrypted with .NET Framework Data Provider