当我希望一列具有不同的值时,可以使用约束

create table t1(
id int primary key,
code varchar(10) unique NULL
);
go


,也可以使用唯一索引

create table t2(
id int primary key,
code varchar(10) NULL
);
go

create unique index I_t2 on t2(code);


具有唯一约束的列似乎是唯一索引的良好候选者。

是否存在使用唯一约束而不使用唯一索引的已知原因? br />

评论

他们实际上不同吗?我认为在某些数据库中PostgreSQL,唯一约束仅创建唯一索引。我没有回答,因为我对sql server一无所知。

在postgresql中,可以在唯一索引中使用表达式,但不能在唯一约束中使用表达式。

在MS SQL上,它们的实现方式相同。尝试使用相同的数据创建两个表,一个表具有唯一约束,另一个表具有唯一索引。它们将使用相同数量的索引空间,并且两者都将能够针对以任何一种方式创建的唯一索引(在实践中)。

#1 楼

在引擎盖下,唯一约束的实现方式与唯一索引相同-需要一个索引来有效满足强制执行约束的要求。即使索引是由于UNIQUE约束而创建的,如果查询计划程序认为索引是处理给定查询的最佳方法,它也可以像其他索引一样使用它。

因此对于数据库同时支持这两种功能的选择通常取决于首选样式和一致性。

如果您打算将索引用作索引(即您的代码可能依赖于搜索/排序/快速过滤该字段)我将明确使用唯一索引(并注释源代码),而不是使用约束来使内容更清楚-如果在您(或其他一些应用程序)的更高版本中更改了唯一性要求,则可以采用这种方式编码人员)将知道确保将非唯一索引替换为唯一索引(仅删除唯一约束将完全删除索引)。还可以在索引提示中命名特定索引(即WITH(INDEX(ix_index_name))),我认为在幕后创建的用于管理唯一性的索引不是这种情况,因为您不太可能知道其名称。 br />
同样,如果您只需要将唯一性作为业务规则来执行,而不是需要搜索或用于排序的字段,那么我将使用约束,再次使某人使用时,其用途更加明显否则,请查看表定义。

请注意,如果在同一字段上同时使用唯一约束和唯一索引,则数据库的亮度将不足以查看重复项,因此最终结果是两个索引将占用额外的空间并减慢行插入/更新的速度。

评论


@jae:一个DBMS当然可以足够明亮,但是您必须与每个DBMS一起检查它是否亮。如果您要求MSSQL创建两个相同的索引,它将创建两个而不是两个被两个名称引用的索引(至少上次我发现这种情况是这种情况(由于我的复制+粘贴错误)),因此,我假设由于约束而存在其中一个索引的情况也是如此。

– David Spillett
2011年1月4日,12:51

+1 @David Spillett我认为DBMS基本上只是假设您知道自己在做什么;如果您想两次创建相同的索引,则不会对此提出质疑。

–安德鲁·巴伯(Andrew Barber)
2011年1月11日22:32

非常有见地。您是否知道这种行为是否也存在于MySQL和Apache Derby中?

– corsiKa
2011年5月18日在15:23

您可以命名约束并在索引提示中使用它。创建表#T(X INT CONSTRAINT PK主键已删除);选择*来自#T WITH(INDEX(PK))WHERE X =1。尽管约束不支持所有索引选项(例如INCLUDEd),但索引可以更灵活列或过滤索引。

–马丁·史密斯
13年2月8日在11:22

“…唯一约束的实现方式与唯一索引相同”。不,不是。例如,可以禁用唯一索引,可以过滤唯一索引。

–格林斯通·沃克(Greenstone Walker)
2013年12月16日21:10

#2 楼

除了其他答案中的要点之外,这还有两者之间的一些关键区别。

注意:错误消息来自SQL Server2012。

错误

违反唯一约束将返回错误2627。
<违反唯一索引将返回错误2601。

Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'P1U_pk'. Cannot insert duplicate key in object 'dbo.P1U'. The duplicate key value is (1).
The statement has been terminated.


禁用

唯一约束无法禁用。

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.P1' with unique index 'P1_u'. The duplicate key value is (1).
The statement has been terminated.


但是主键约束或唯一约束后面的唯一索引可以被禁用,任何唯一索引也可以被禁用。 Hat-tip Brain2000。

Msg 11415, Level 16, State 1, Line 1
Object 'P1U_pk' cannot be disabled or enabled. This action applies only to foreign key and check constraints.
Msg 4916, Level 16, State 0, Line 1
Could not enable or disable the constraint. See previous errors.


请注意通常的警告,即禁用聚集索引会使数据不可访问。

选项

唯一约束支持诸如FILLFACTORIGNORE_DUP_KEY之类的索引选项,尽管并非每种版本的SQL Server都如此。

包含的列

非聚集索引可以包括非索引列(称为覆盖索引,这是对性能的重大改进)。 PRIMARY KEY和UNIQUE约束后面的索引不能包含列。帽子提示@ypercube。

过滤

不能过滤唯一约束。

可以过滤唯一索引。

ALTER INDEX P1_u ON dbo.P1 DISABLE ;


外键约束

外键约束不能引用过滤的唯一索引,尽管它可以引用未过滤的唯一索引(我认为这是添加的在SQL Server 2005中)。

命名

创建约束时,指定约束名称是可选的(对于所有五种约束类型)。如果您未指定名称,则MSSQL将为您生成一个名称。

CREATE UNIQUE NONCLUSTERED INDEX Students6_DrivesLicence_u 
ON dbo.Students6( DriversLicenceNo ) WHERE DriversLicenceNo is not null ;


创建索引时,必须指定名称。

帽子@ i-one。

链接

http://technet.microsoft.com/zh-cn/library/aa224827(v=SQL.80).aspx

http:// technet。 microsoft.com/zh-CN/library/ms177456.aspx

评论


可以通过与索引相同的方法来禁用和启用唯一约束:ALTER INDEX tbl ON uconstraint禁用,ALTER INDEX tbl ON uconstraint重建

– Brain2000
18年7月19日在15:03



谢谢@ Brain2000。巧合的是,今天早上,在我阅读此评论之前,我教了一个有关禁用索引的部分。

–格林斯通·沃克(Greenstone Walker)
18年7月20日在1:58

#3 楼

引用MSDN作为权威资料:创建UNIQUE约束和创建独立于约束的唯一索引之间没有显着差异。数据验证以相同的方式发生,并且查询优化器不会区分由约束创建或手动创建的唯一索引。但是,在列上创建UNIQUE约束可以使索引的目标明确...更多信息在这里


和...数据库引擎自动创建一个UNIQUE索引以强制执行UNIQUE约束的唯一性要求。因此,如果尝试插入重复的行,则数据库引擎将返回错误消息,指出已违反UNIQUE约束,并且不会将行添加到表中。除非明确指定聚集索引
,否则默认情况下会创建唯一的非聚集索引,以强制执行UNIQUE约束。 :https://technet.microsoft.com/zh-CN/library/aa224827%28v=sql.80%29.aspx

#4 楼

唯一约束和唯一索引之间的主要区别之一是,另一个表上的外键约束可以引用构成唯一约束的列。对于唯一索引,情况并非如此。另外,唯一约束被定义为ANSI标准的一部分,而索引则未被定义。最后,当索引是物理方面时,唯一约束被认为存在于逻辑数据库设计领域(可以由不同的DB引擎以不同方式实现)。因此,唯一约束更具声明性。
在几乎所有情况下,我都希望唯一约束。

评论


-1在SQL Server中,以下情况是错误的:“另一个表上的外键约束可以引用构成唯一约束的列。对于唯一索引而言,这不是正确的”。在SQL Server中,我们可以将FK约束引用到唯一索引。

–A-K
2012年5月2日在20:31

我认为,SQL Server 2005中增加了外键约束引用唯一索引的功能。许多资源(包括BOL中的某些页面)尚未更新以反映所做的更改,因此我不认为Dmitry的答案值得downvotes。他其余的答案就在现场-约束是ANSI标准的,索引不是。

–格林斯通·沃克(Greenstone Walker)
2013年12月16日21:08



标准很重要。如果Ansi标准要使用唯一约束,那么我们应该使用唯一约束。

–琉璃
17年9月19日在17:56

#5 楼

在Oracle中,主要区别在于您可以创建一个函数唯一索引,该索引不能在唯一约束下使用:例如,

create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);


因此,fk_xyz仅对于具有amount != 0的记录是唯一的。

评论


在SQL Server(问题的标记)中,可以使用WHERE子句过滤索引。在TXT ='qwert'的DBO.P4(PID)上创建唯一的非索引索引P4_U;

–格林斯通·沃克(Greenstone Walker)
2013年12月16日21:23



#6 楼

首选UNIQUE约束优于UNIQUE索引。当约束不是唯一的时,您需要使用常规或非唯一索引。约束也是索引的另一种类型。索引用于更快地访问。

唯一索引可以具有where子句。例如,您可以基于日期列为每一年创建索引

WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'


评论


“约束也是索引的另一种类型。”不,不是。某些约束(PK,UQ,FK)可以并且经常通过使用索引来强制实施。不一定,但并非所有DBMS都默认。

–超立方体ᵀᴹ
17-2-8在10:33