应用Always Encrypt后主键与默认约束丢失,是否为正常现象?
问题描述
已在SQL Server 2022中成功配置带Secure Enclave的Always Encrypt(无证明),通过以下代码创建表:
CREATE TABLE dbo.tbTesting ( idData INT PRIMARY KEY, descData VARCHAR(200), inputTime DATETIME DEFAULT GETDATE() ); GO
表创建成功后,使用SSMS右键表选择「加密列」功能,对descData列采用Randomized加密类型并启用Enclave加密,操作完成后发现idData列的主键约束和inputTime列的默认约束丢失,需通过以下代码重建:
ALTER TABLE dbo.tbTesting ADD PRIMARY KEY (idData); ALTER TABLE dbo.tbTesting ADD CONSTRAINT dtInputTime DEFAULT GETDATE() FOR inputTime;
疑问:这是Always Encrypt的正常效果、bug,还是对Always Encrypt的认知盲区?
环境信息:
- Microsoft SQL Server 2022 (RTM) - 16.0.1000.6 (X64),Developer Edition(64位)
- 操作系统:Windows 10 Home Single Language 10.0 (Build 19045)(Hypervisor)
- SSMS版本:19.1.56.0
分析与解答
这既不是Always Encrypt的正常效果,也不是功能bug,而是SSMS图形化加密向导的实现逻辑导致的局限性。
SSMS的「加密列」向导在执行加密操作时,内部采用创建新表→迁移原表数据→删除旧表→重命名新表的流程。这个过程中,向导只会迁移表的基础结构和数据,不会自动同步原表的主键、默认约束、索引、触发器等附属对象——因为该工具的设计核心是快速完成列加密操作,并未覆盖完整的表对象迁移场景。
解决方案
- 手动重建约束(当前采用的方式):加密前先备份原表的所有约束、索引定义,加密完成后手动执行语句重建。
- 改用T-SQL直接加密列:避免使用SSMS图形化工具,直接通过
ALTER TABLE语句加密列,这种方式会保留原表的所有约束。示例代码如下(需替换为你的列加密密钥名):
ALTER TABLE dbo.tbTesting ALTER COLUMN descData VARCHAR(200) ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = [你的列加密密钥名称], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ) WITH (ENCLAVE_COMPUTATIONS = ON); GO
注意:执行该语句前,需确保SSMS连接已启用「Always Encrypted」和「安全飞地计算」(在连接属性的「Always Encrypted」选项卡中勾选对应选项)。
内容的提问来源于stack exchange,提问作者Liudi Wijaya
相关产品推荐
相关产品推荐

