SQL Server Always Encrypted:操作数类型冲突:varchar 与 varchar(max) 不兼容

Posted

技术标签:

【中文标题】SQL Server Always Encrypted:操作数类型冲突:varchar 与 varchar(max) 不兼容【英文标题】:SQL Server Always Encrypted: Operand type ***: varchar is incompatible with varchar(max) 【发布时间】:2018-05-15 07:16:13 【问题描述】:

由于我们即将在英国实施法规变更,因此我正在开发的数据库需要更新,以便对任何个人身份信息进行加密。

我的一些表已成功更改,但是在某些有触发器的表上,我收到以下错误。

错误 SQL72014:.Net SqlClient 数据提供程序:消息 206,级别 16,状态 2,过程 tr_Employee_Update,第 27 行操作数类型冲突:varchar 与使用 (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = ' 加密的 varchar(max) 不兼容AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_Auto1', column_encryption_key_database_name = 'xxxx') collat​​ion_name = 'Latin1_General_BIN2'

我在这里看过这个问题,但这并不能解决我的问题Operand type ***: varchar is incompatible with varchar(50) trying to insert in encrypted database

这个问题也一样,哪里没有完全解决我的问题。 SQL Server Always Encrypted Operand type ***: varchar is incompatible with varchar(60) when running EXEC sproc.

我在许多桌子上都遇到了这个问题,因此非常感谢您提供任何帮助。

请在此处查看 SQL Fiddle

http://sqlfiddle.com/#!18/4ac5c/3

我不得不拆分表并创建触发器,因为 SQL 长度大于 8000 个字符,但这是我能给出的最完整的示例。

我正在使用加密类型加密列:确定性和加密密钥名称:CEK_Auto1。

并非此表中的所有列都需要加密,并且我正在更改其他一些具有默认值的字段,这些字段也需要进行加密。

我们将不胜感激地收到有关所报告问题的任何和所有帮助。

CREATE TABLE [dbo].[Employee] (
[EmployeeID]        INT           IDENTITY (1, 1) NOT NULL,
[EmployeeTypeID]    INT           NOT NULL,
[Title]             VARCHAR (50)  NOT NULL,
[Forename]          VARCHAR (30)  NOT NULL,
[Surname]           VARCHAR (30)  NOT NULL,
[AddressLine1]      VARCHAR (60)  NOT NULL,
[AddressLine2]      VARCHAR (60)  NOT NULL,
[AddressLine3]      VARCHAR (60)  NOT NULL,
[AddressLine4]      VARCHAR (60)  NOT NULL,
[Town]              VARCHAR (50)  NOT NULL,
[County]            VARCHAR (50)  NOT NULL,
[PostCode]          VARCHAR (20)  NOT NULL,
[Phone]             VARCHAR (20)  CONSTRAINT [DF_Employee_Phone] DEFAULT ('') NOT NULL,
[Mobile]            VARCHAR (20)  NOT NULL,
[Fax]               VARCHAR (20)  NOT NULL,
[Email]             VARCHAR (50)  NOT NULL,
[Extension]         VARCHAR (10)  CONSTRAINT [DF_Employee_Extension_1] DEFAULT ('') NOT NULL,
[SpeedDial]         VARCHAR (10)  CONSTRAINT [DF_Employee_SpeedDial_1] DEFAULT ('') NOT NULL,
[Notes]             VARCHAR (MAX) NOT NULL,
[EmployeeTeamID]    INT           NULL,
[Created]           DATETIME      CONSTRAINT [DF_Employee_Created] DEFAULT (getdate()) NOT NULL,
[OperatorIDCreated] INT           NOT NULL,
[Updated]           DATETIME      CONSTRAINT [DF_Employee_Updated] DEFAULT (getdate()) NOT NULL,
[OperatorIDUpdated] INT           NOT NULL,
[Deleted]           BIT           CONSTRAINT [DF_Employee_Deleted] DEFAULT ((0)) NOT NULL,
[EmployeeIDManager] INT           NULL,
[JobTitle]          VARCHAR (100) CONSTRAINT [DF_Employee_JobTitle] DEFAULT ('') NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED ([EmployeeID] ASC),
CONSTRAINT [FK_Employee_Employee] FOREIGN KEY ([EmployeeIDManager]) REFERENCES [dbo].[Employee] ([EmployeeID]),
CONSTRAINT [FK_Employee_EmployeeTeam] FOREIGN KEY ([EmployeeTeamID]) REFERENCES [dbo].[EmployeeTeam] ([EmployeeTeamID]),
CONSTRAINT [FK_Employee_EmployeeType] FOREIGN KEY ([EmployeeTypeID]) REFERENCES [dbo].[EmployeeType] ([EmployeeTypeID])
);


GO
CREATE NONCLUSTERED INDEX [IX_Employee_Surname]
ON [dbo].[Employee]([Surname] ASC);


GO

CREATE TABLE [dbo].[AuditItem](
[AuditItemID] [INT] IDENTITY(1,1) NOT NULL,
[ID] [INT] NOT NULL,
[AuditEntityID] [INT] NOT NULL,
[AuditTypeID] [INT] NOT NULL,
[Note] [VARCHAR](MAX) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_Auto1], ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,
[Created] [DATETIME] NOT NULL,
[OperatorIDCreated] [INT] NOT NULL,
[ProfessionalIDCreated] [INT] NULL,
 CONSTRAINT [PK_AuditItem] PRIMARY KEY CLUSTERED 
(
[AuditItemID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

    ALTER Trigger  [dbo].[tr_Employee_Update] ON [dbo].[Employee] 
FOR UPDATE

AS

--Audit Entity ID for Employees
Declare @AuditEntityID int
set @AuditEntityID = 2

Insert AuditItem
    (ID,AuditEntityID,AuditTypeID, Note, Created, OperatorIDCreated)
Select
    inserted.EmployeeID,
    @AuditEntityID,
    --Update type
    2,
    'Name changed from ' + ltrim(rtrim(ltrim(rtrim(Deleted.Title)) + ' ' + ltrim(rtrim(Deleted.Forename)) + ' ' + ltrim(rtrim(Deleted.Surname)))) + ' to ' + + ltrim(rtrim(ltrim(rtrim(Inserted.Title)) + ' ' + ltrim(rtrim(Inserted.Forename)) + ' ' + ltrim(rtrim(Inserted.Surname)))),
    GetDate(),
    inserted.OperatorIDUpdated
From inserted
        Inner Join deleted on inserted.EmployeeID = deleted.EmployeeID
Where deleted.Title <> inserted.Title or deleted.Forename <> inserted.Forename or deleted.Surname <> inserted.Surname

【问题讨论】:

代表 Youfah Mizzum - 当您更改表时,请在更改前尝试禁用触发器。更改后,触发器是否可以重新启用? 你链接了其他问题并说它们不起作用,你能详细说明吗? 现在试试这个 @WhatsThePoint,是的,不要以现有存储过程的方式解决我的问题,这是我正在使用的表上的触发器。因此,加密本来已经能够发生。触发器在加密点被击中。 禁用触发器不起作用 BTW 【参考方案1】:

今天对此进行了大量研究后,不幸的是,目前不支持触发器来更新加密列,无论数据类型如何。因此,任何偶然发现此问题并遇到相同问题的人都需要通过存储过程完成更新,但需要通过应用程序代码调用它们。

虽然我上面的问题中的两个链接问题没有直接解决我的问题或帮助我,但如果您需要将参数化值传递给存储过程并遇到问题,您可能需要按照问题中的答案来帮助您。

【讨论】:

以上是关于SQL Server Always Encrypted:操作数类型冲突:varchar 与 varchar(max) 不兼容的主要内容,如果未能解决你的问题,请参考以下文章

Sql Server Always On 读写分离配置方法

Windows Server 2012搭建SQL Server Always On踩坑全记录

SQL Server Always ON 数据同步原理

SQL SERVER ALWAYS ON 之 添加新的同步数据库

Skype for Business Server 部署SQL always on 已知问题

SQL Server Always Encrypted 与 .NET Core 不兼容