Sql Alter table在不检查SSDT的情况下添加唯一约束

Sql Alter table在不检查SSDT的情况下添加唯一约束,sql,sql-server,sql-server-data-tools,dacpac,Sql,Sql Server,Sql Server Data Tools,Dacpac,我有一个SSDT项目,我们通过dacpac/sqlpackage发布数据库。 现在我有了一个包含重复记录的现有表。 我添加了一个唯一的约束,这样记录就不会被复制。 这就是我的表脚本的样子 CREATE TABLE [AM].[WorkflowStep] ( [Id] INT NOT NULL PRIMARY KEY IDENTITY, [StepName] NVARCHAR(200) NOT NULL, [IsAutomated] BIT NOT NULL DEFAU

我有一个SSDT项目,我们通过dacpac/sqlpackage发布数据库。 现在我有了一个包含重复记录的现有表。 我添加了一个唯一的约束,这样记录就不会被复制。 这就是我的表脚本的样子

CREATE TABLE [AM].[WorkflowStep]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
    [StepName] NVARCHAR(200) NOT NULL, 
    [IsAutomated] BIT NOT NULL DEFAULT 0, 
    [TenantId] UNIQUEIDENTIFIER NOT NULL,
    *CONSTRAINT [UNIQUE_STEP] UNIQUE (StepName, IsAutomated, TenantId)*
)
约束是新添加的。我希望
sqlpackage.exe
生成带有约束的发布脚本,该约束添加了
NOCHECK
选项,然后最后使用
CHECK
选项进行更改。但事实并非如此。该脚本只有一个alter table选项

ALTER TABLE [WorkflowStep]
    ADD CONSTRAINT [UNIQUE_STEP] UNIQUE NONCLUSTERED ([StepName] ASC, [IsAutomated] ASC, [TenantId] ASC);

有人能解释为什么会这样吗?这是否特定于
唯一
约束。我在其他表中有其他约束,sqlpackage最初使用
NOCHECK
选项为这些表添加约束,但它们是外键引用。`

您可以自己轻松测试:

创建表#t(ID int);
插入#t(ID)值(1)、(1);
使用NOCHECK ADD CONSTRAINT UQ#t#ID UNIQUE(ID)更改表#t;
CREATE UNIQUE INDEX语句终止,因为为对象名“dbo.#t..”和索引名“UQ#t#u ID”找到了重复的键。重复的键值为(1)

这证明忽略了
NOCHECK
。也仅为
外键
检查
约束指定效果,尽管它们没有说明其他约束的行为

它以这种方式工作有一个很好的技术原因:
UNIQUE
约束必须由索引支持,并且
UNIQUE
索引的物理结构不同于非
UNIQUE
索引。具体来说,非
唯一的
索引有一个uniquifier,一个不可见的、可为空的整数列添加到索引行中,以使它们无论如何都是唯一的,并允许引擎识别单个行。要允许使用NOCHECK创建唯一约束
,然后稍后使用CHECK应用
,实际上需要重建索引,至少要更改元数据——这并不比从一开始就正确地创建索引为
唯一的
或非
唯一的
,好得多,取决于你需要什么。相比之下,
外键
/
检查
约束始终可以在以后验证,而无需重写数据