需要在SQL Server中具有带加密列的表上触发,以便将每次更新的新记录插入存档表

问题描述

我有一个类似于sql Server 2017中以下架构的表:

使用sql Server“始终加密”功能Sample列进行加密的主数据库中的表TaxID

CREATE TABLE [dbo].[Sample]
(
    [CreatedDt] [smalldatetime] NOT NULL,[LastModDt] [smalldatetime] NOT NULL,[CompanyID] [int] IDENTITY(1,1) NOT NULL,[CompanyName] [varchar](250) NOT NULL,[CompanyTaxName] [varchar](250) NULL,[TaxID] [varchar](15) COLLATE latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = 
    [CEK_Auto1],ENCRYPTION_TYPE = Deterministic,ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL,[Active] [bit] NOT NULL
)

然后,出于历史记录的目的,存档数据库中还有另一个具有相同架构的表,其中TaxID已加密。

这是Sample数据库中的表Main_Archive

CREATE TABLE [dbo].[Sample]
(
    [CreatedDt] [smalldatetime] NOT NULL,[CompanyArchiveID] [int] IDENTITY(1,[Active] [bit] NOT NULL
)

现在,我们希望在主Sample表上有一个触发器,以便在每次更新时将新记录插入到存档Sample表中。

数据库Sample表的触发器如下:

CREATE TRIGGER [dbo].[tr_iud_Sample] 
ON [dbo].[Sample]
FOR INSERT,UPDATE,DELETE
AS 
BEGIN
    SET NOCOUNT ON
    DECLARE @CurrDt AS SMALLDATETIME
    SELECT @CurrDt = GETDATE()

    DECLARE @CurrYear AS INT
    SELECT @CurrYear = YEAR(@CurrDt)

    UPDATE Sample
    SET LastModDt = @CurrDt,CreatedDt = CASE WHEN d.CompanyID IS NULL THEN @CurrDt ELSE Sample.CreatedDt END
    FROM inserted i WITH (NOLOCK)
    LEFT JOIN deleted d WITH (NOLOCK) ON d.CompanyID= i.CompanyID
    WHERE Sample.CompanyID = i.CompanyID 

    INSERT INTO [Main_Archive].[dbo].Sample
        SELECT CreatedDt,LastModDt,CompanyID,CompanyName,CompanyTaxName,TaxID,Active
        FROM deleted
END

ALTER TABLE [dbo].[Sample] ENABLE TRIGGER [tr_iud_Sample]
GO

ALTER TABLE [dbo].[vendor] disABLE TRIGGER [tr_iud_Sample]
GO

但这失败了,我得到这个错误

消息4920,级别16,状态0,第50行
操作数类型冲突:varchar(15)用(encryption_type ='DETERMINISTIC',encryption_algorithm_name ='AEAD_AES_256_CBC_HMAC_SHA_256',column_encryption_key_name ='CEK_Auto1',column_encryption_key_database_name ='NCI_COMMON'='NCI_COMMON'

有没有一种方法可以对加密表进行触发,如果可以,如何实现 所需的功能

此外,如果sql Server当前不支持功能,是否有任何解决方法可以实现?

提前谢谢

解决方法

在使用Always Encrypted的SQL Server版本System-Versioned Temporal Tables时。

您可以使表成为系统版本,并将维护历史记录的工作留给SQL Server引擎(同样,当您更改表设计时,引擎将减轻对历史记录表的更改)。

可以使用特殊子句queried来临时表,并为您提供分析历史数据的新方法。

我面临的一个缺点是,历史记录表的列必须与目标表的列相匹配-因此,如果您需要在历史记录中包含ModifiedBy列,则必须更改应用程序以在原始表。