我有一个名为countries
的表,我通过在SQL Server 2008 R2上创建“唯一键”类型的“索引/键”来定义country_name
列是唯一的。
但我有以下问题:
IsUnique
值保持为“是”,那么会有任何差异吗?在幕后将唯一约束作为唯一索引实现,因此指定它并不重要。我倾向于简单地实现它:
ALTER TABLE dbo.foo ADD CONSTRAINT UQ_bar UNIQUE(bar);
有些人会创建一个唯一的索引,例如
CREATE UNIQUE INDEX IX_UQ_Bar ON dbo.foo(bar);
不同之处在于意图 - 如果要创建约束以强制执行唯一性/业务规则,则创建约束,如果这样做是为了帮助查询性能,则创建唯一索引可能更合乎逻辑。同样,在幕后它是相同的实施,但你走到那里的道路可能有助于记录你的意图。
我认为有多种选择可以遵循以前的Sybase功能以及遵守ANSI标准(即使唯一约束不符合标准100%,因为它们只允许一个NULL值 - 一个唯一索引,另一方面,可以通过在SQL Server 2008及更高版本上添加WHERE
子句(WHERE col IS NOT NULL
)来解决这个问题。
还有一点需要注意的是,如果您创建索引,则可以指定包含的列,如果通过country_name进行搜索,这可以帮助您的SQL代码更快地运行。
CREATE UNIQUE NONCLUSTERED INDEX IX_UQ_Bar
ON dbo.foo (
bar
)
INCLUDE (foo_other_column)
GO
SELECT foo_other_column FROM Foo WHERE bar = 'test'
SQL服务器将在索引本身中存储“foo_other_column”。在唯一约束的情况下,它将首先找到'test'的索引,然后将在foo表中搜索行,并且仅在那里它将采用“foo_other_column”。
唯一索引或唯一约束之间没有区别,也没有性能差异。但是,创建时存在一些差异,其中某些索引创建选项不可用于唯一约束。
如果您使用SqlMetal.exe输出DBML或LinqToSql实体:
原因是在实现SqlMetal。它查询数据库信息模式,特别是关键列使用情况。在那里表示唯一键,但不是唯一索引。
SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, ORDINAL_POSITION
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
除了上面的优秀答案,我在这里加2美分。
唯一键是约束,它使用唯一索引来强制执行自身。正如主键通常由集群唯一索引强制执行一样。从逻辑上讲,约束和索引是两回事。但是在RDBMS中,可以通过索引物理地实现约束。
如果在sql server中使用唯一约束创建表,您将看到约束对象和唯一索引
create table dbo.t (id int constraint my_unique_constraint unique (id));
select [Constraint]=name from sys.key_constraints
where parent_object_id = object_id('dbo.t');
select name, index_id, type_desc from sys.indexes
where object_id = object_id('dbo.t')
and index_id > 0;
我们将得到以下(约束和索引)
但是,如果我们不创建约束,而只是创建一个唯一索引,如下所示
create table dbo.t2 (id int );
create unique index my_unique_constraint on dbo.t2 (id);
select [Constraint]=name from sys.key_constraints
where parent_object_id = object_id('dbo.t2');
select name, index_id, type_desc from sys.indexes
where object_id = object_id('dbo.t2')
and index_id > 0
您将看到没有创建约束对象(仅创建索引)。
从“理论”的角度来看,在SQL Server中,约束是具有object_id值且受模式约束的对象,而索引不是对象且没有object_id值且没有与模式相关。
强制唯一性的第三个选项是使用Filtered Unique-Index来允许Nullable Unique Index。
这不适用于Unique-Constraints。
例如,假设您有一个列,您只想允许唯一值,
但是当它们不存在时仍然希望支持多个NULL
值。
只有过滤的唯一索引才有效:
CREATE UNIQUE NONCLUSTERED INDEX [UF_Employee_UserID] ON [dbo].[Employee]
(
[UserID] ASC--Not all Employees have a UserID to log into the System.
)
WHERE ([UserID] IS NOT NULL)--Enforce Uniqueness when not null.
现在,在使用GUI编辑表时,仍然无法在SSMS中创建Filtered-Index。 但是,如果您想通过GUI而不是手动创建索引(如上所述),则可以关闭所有打开的表设计器,然后在对象资源管理器中打开索引本身的属性。
最重要的一点是假设您希望保持列值null并保持唯一性,而不能使用唯一键约束但使用唯一键索引u可以使列值保持为null并保持唯一性。因此,如果您需要具有Null-able类型唯一索引的列唯一索引,如果您需要列不能为空,则需要唯一键约束。