在Microsoft SQL Server中,在创建表时,即使您并不真的需要它是唯一的,在列上使用唯一约束是否有任何缺点?
一个例子是对用户管理系统中的角色的描述:
CREATE TABLE Role
(
ID TINYINT PRIMARY KEY NOT NULL IDENTITY(0, 1),
Title CHARACTER VARYING(32) NOT NULL UNIQUE,
Description CHARACTER VARYING(MAX) NOT NULL UNIQUE
)
我担心在其他表中频繁插入时验证此约束将是一个非常耗时的过程。我不确定如何验证这种约束,但我觉得它可以以一种非常有效的方式或线性比较来完成。
答案 0 :(得分:4)
你的恐惧变为真实:UNIQUE约束被实现为索引,这是时间和空间消耗。
因此,无论何时插入新行,数据库都必须更新表,并且还要为每个唯一约束更新一个索引。
所以,据你说:
在列上使用唯一约束,即使您并不真正需要它是唯一的
答案是否定的,不要使用它。有时间和空间的缺点。
您的样本表需要Id的聚簇索引和2个额外索引,每个唯一约束一个。这占用了空间和时间来更新插入的3个索引。
只有通过这些字段进行过滤查询才能证明这一点。
按方式: 原始的样本后表有几个缺陷:
该语法不是SQL Server语法(并将其标记为SQL Server)
您无法在varchar(max)列中创建索引
如果您更正语法并创建此表:
CREATE TABLE Role
(
ID tinyint PRIMARY KEY NOT NULL IDENTITY(0, 1),
Title varchar(32) NOT NULL UNIQUE,
Description varchar(32) NOT NULL UNIQUE
)
然后您可以执行sp_help Role
并找到3个索引。
答案 1 :(得分:1)
数据库创建一个备份UNIQUE约束的索引,因此进行唯一性检查应该是非常低成本的。
http://msdn.microsoft.com/en-us/library/ms177420.aspx
数据库引擎自动创建UNIQUE索引以强制执行UNIQUE约束的唯一性要求。因此,如果尝试插入重复行,则数据库引擎将返回一条错误消息,指出违反了UNIQUE约束并且未将该行添加到表中。除非显式指定聚簇索引,否则默认情况下会创建唯一的非聚簇索引以强制执行UNIQUE约束。
答案 2 :(得分:0)
如果您了解数据,通常是一种限制它的好习惯 将始终是独一无二的,但它不一定是唯一的 应用程序正常运行?
我向你提出的问题:两个角色有不同的标题,但相同的描述是否有意义?例如
INSERT INTO Role ( Title , Description )
VALUES ( 'CEO' , 'Senior manager' ),
( 'CTO' , 'Senior manager' );
对我而言,似乎贬低了描述的使用;如果有很多重复,那么做更像这样的事情会更有意义:
INSERT INTO Role ( Title )
VALUES ( 'CEO' ),
( 'CTO' );
INSERT INTO SeniorManagers ( Title )
VALUES ( 'CEO' ),
( 'CTO' );
然而,你再也不期待重复。
我认为这是一个低活动表。你说你担心在其他表中频繁插入时验证这个约束。好吧,这不会发生(除非有一个触发器,我们看不到可能在更新另一个表时更新此表)。
就个人而言,我会要求设计师(商业分析师,无论如何)证明不应用唯一约束。如果他们不能,那么我会根据常识强加不合理的约束。与通常的此类文本列一样,我也会应用CHECK
个约束,例如禁止前导/尾随/双重空格,零长度字符串等
答案 3 :(得分:-1)
在SQL Server上,数据类型tinyint仅为您提供256个不同的值。无论你在id列之外做什么,你都不会得到一张非常大的桌子。即使有十几个索引列,它肯定会很快执行。
但是,除了代理键之外,您通常还需要至少一个唯一约束。如果你没有,你可能会得到这样的数据。
1 First title First description
2 First title First description
3 First title First description
...
17 Third title Third description
18 First title First description
允许这样的数据的表通常是错误的。任何使用此表的外键引用的表都无法正确报告,例如,使用的“第一个标题”的数量。
我认为在用户管理系统中为角色允许多个相同的标题是一个设计错误。我可能会说“标题”对于那个专栏来说也是一个非常糟糕的名字。