CREATE TABLE table1 (foo int, bar int);
CREATE UNIQUE INDEX ux_table1_foo ON table1(foo); -- Create unique index on foo.
INSERT INTO table1 (foo, bar) VALUES (1, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (2, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (3, 1); -- OK
INSERT INTO table1 (foo, bar) VALUES (1, 4); -- Fails!
Duplicate entry '1' for key 'ux_table1_foo'
最后一次插入失败,因为当它尝试将值1第二次插入此列时,它违反了列 foo 上的唯一索引 .
在MySQL中,唯一约束允许多个NULL .
可以在多列上创建唯一索引 .
Primary key versus unique index
事情是一样的:
主键表示唯一索引 .
不同的事情:
主键也暗示NOT NULL,但唯一索引可以为空 .
只能有一个主键,但可以有多个唯一索引 .
如果没有定义聚簇索引,则主键将是聚簇索引 .
5
你可以这样看:
A Primary Key IS Unique
A Unique value doesn't have to be the Representaion of the Element
15 回答
CLUSTERED INDEXES与UNIQUE INDEXES有一些缺点 .
如前所述,CLUSTERED INDEX对表中的数据进行物理排序 .
这意味着当你在包含聚簇索引的表上插入或删除很多时,每次(好吧,差不多,取决于你的填充因子)你更改数据,物理表需要更新以保持排序 .
在相对较小的表中,这很好,但是当获得具有GB数据的表,并且插入器/删除器影响排序时,您将遇到问题 .
What is a unique index?
列上的唯一索引是该列上的索引,该索引还强制执行约束,即该列中的两个不同行中不能有两个相等的值 . 例:
最后一次插入失败,因为当它尝试将值1第二次插入此列时,它违反了列
foo
上的唯一索引 .在MySQL中,唯一约束允许多个NULL .
可以在多列上创建唯一索引 .
Primary key versus unique index
事情是一样的:
不同的事情:
主键也暗示NOT NULL,但唯一索引可以为空 .
只能有一个主键,但可以有多个唯一索引 .
如果没有定义聚簇索引,则主键将是聚簇索引 .
你可以这样看:
A Primary Key IS Unique
A Unique value doesn't have to be the Representaion of the Element
含义?;好吧,主键用于标识元素,如果您有“人”,您希望拥有个人识别号码(SSN或类似物),这是您的主要人物 .
另一方面,该人可能有一个独特的电子邮件,但不会识别该人 .
我总是有主键,甚至在关系表(中间表/连接表)中我可能有它们 . 为什么?好吧,我喜欢在编码时遵循标准,如果“人”有标识符,汽车有标识符,那么人 - >车也应该有标识符!
外键使用唯一约束以及主键 . 来自联机丛书:
对于事务复制,您需要主键 . 来自联机丛书:
这两个答案都适用于SQL Server 2005 .
选择何时使用代理主键而不是自然键是很棘手的 . 诸如,永远或永远的答案很少有用 . 我发现这取决于具体情况 .
举个例子,我有以下表格:
我们有两个实体表(
toll_booths
和cars
)和一个事务表(drive_through
) .toll_booth
表使用代理键,因为它没有保证不会更改的自然属性(名称可以轻松更改) .cars
表使用自然主键,因为它具有不变的唯一标识符(vin
) .drive_through
事务表使用代理键以便于识别,但对于在插入记录时保证唯一的属性也有唯一约束 .http://database-programmer.blogspot.com有一些关于这一特定主题的精彩文章 .
主键没有缺点 .
要仅向@MrWiggles和@Peter Parker答案添加一些信息,例如当表没有主键时,您将无法在某些应用程序中编辑数据(他们最终会说无法编辑/删除数据首要的关键) . Postgresql允许多个NULL值在UNIQUE列中,PRIMARY KEY不允许NULL . 此外,一些生成代码的ORM可能会对没有主键的表有一些问题 .
更新:
据我所知,在MSSQL中无法复制没有主键的表,至少没有问题(details) .
如果某些东西是主键,则根据您的数据库引擎,整个表将按主键排序 . 这意味着主键上的查找速度要快得多,因为它不必进行任何解除引用,因为它与任何其他类型的索引有关 . 除此之外,这只是理论 .
只要你不允许对一个值使用NULL,它们应该被处理相同,但是在数据库上处理值NULL是不同的(AFAIK MS-SQL不允许多于一个(1)NULL值,mySQL和Oracle允许这样做,如果一个列是UNIQUE)所以你 must 定义这个列NOT NULL UNIQUE INDEX
在关系数据理论中没有关键词,所以你的问题必须在实际层面得到回答 .
唯一索引不是SQL标准的一部分 . DBMS的特定实现将确定声明唯一索引的后果 .
在Oracle中,声明主键将导致代表您创建唯一索引,因此问题几乎没有实际意义 . 我无法告诉你有关其他DBMS产品的信息 .
我赞成声明一个主键 . 这具有禁止键列中的NULL以及禁止重复的效果 . 我也赞成声明REFERENCES约束来强制实体完整性 . 在许多情况下,声明外键的coulmn(s)索引会加速连接 . 这种索引通常不应该是唯一的 .
除了其他答案所说的内容之外,一些数据库和系统可能需要存在主数据库 . 一种情况浮现在脑海中;在使用Informix进行企业复制时,必须存在PK才能使表参与复制 .
我几乎从不创建没有数字主键的表 . 如果还有一个应该是唯一的自然键,我还会在其上添加一个唯一索引 . 连接在整数上比在多列自然键上更快,数据只需要在一个地方进行更改(自然键往往需要更新,这在主键中是一件坏事 - 外键关系) . 如果您将需要复制,请使用GUID而不是整数,但在大多数情况下,我更喜欢用户可读的密钥,特别是如果他们需要看到它来区分John Smith和John Smith .
我没有创建代理键的次数是我有一个涉及多对多关系的连接表 . 在这种情况下,我将两个字段声明为主键 .
我的理解是主键和具有非空约束的唯一索引是相同的(*);我想根据规范明确指出或暗示的内容(你要表达和明确强制执行的内容)选择一个或另一个 . 如果它需要唯一性而不是null,那么将它作为主键 . 如果只是发生了唯一索引的所有部分都不为null而没有任何要求,那么只需将其作为唯一索引 .
唯一剩下的区别是,您可能有多个非空的唯一索引,而您不能有多个主键 .
(*)除了实际差异之外:主键可以是某些操作的默认唯一键,例如定义外键 . 防爆 . 如果定义引用表的外键并且不提供列名,如果引用的表具有主键,则主键将是引用的列 . 否则,必须明确命名引用的列 .
这里的其他人提到了数据库复制,但我不知道 .
唯一索引可以有一个NULL值 . 它创建了非集群索引 . 主键不能包含NULL值 . 它创建了CLUSTERED INDEX .
在MSSQL中,主键应该单调增加,以便在聚簇索引上获得最佳性能 . 因此,具有标识插入的整数优于可能不是单调增加的任何自然键 .
您应该始终添加唯一的自动索引ID列 .
然后,除了创建可更新视图或选择之外,您应该继续忽略该列的所有意图和目的 .
例如,永远不要将ID列用作外键或将其用于应用程序中的查找 .
主键主要由数据库使用本身是为了唯一地标识表中的每一行 .
数据库识别逻辑记录而不是物理记录是有 Value 的 - 即多表选择或视图中rowid()的值是多少 .
还要考虑创建可更新视图,必须包含视图中所有表的主键 - 为每个表包含单个id列要容易得多,而不是必须包含每个表的复合主键的所有部分 . 表 .
总之,数据库及其优化器使用主键 - 应用程序不应将其用于创建可更新视图以外的任何其他内容 . 应用程序所需的所有查找和关系应由所需列上的索引支持,并且应明确不使用主键 .
在数据库的更深层次上,通常rowid()可以为每一行提供一个uniqie密钥,但它识别表中的物理行,而不是逻辑行 - 前者可以通过维护操作进行修改,而后者将始终识别独特的逻辑行 .
其他索引很可能实际上是将索引键值映射到主键值,而不是rowid() . 这允许在不必重新创建这些索引的情况下进行物理排序操作 .