我正在为一个新项目设计新的数据库,并且我面临一个两难境地:
在数据库理论中,主键是基础元素,这没问题,但在实际项目中,两者各自有什么优缺点?
你在项目中使用哪种方式?
编辑:在 MS SQL 服务器上进行复制时,主键又有什么影响?
什么是唯一索引?
在一个列上创建的唯一索引除了创建该列的索引外,还强制要求此列在不同行中不能有两个相等的值。例如:
CREATE TABLE table1 (foo int, bar int); CREATE UNIQUE INDEX ux_table1_foo ON table1(foo); -- 在foo列上创建唯一索引。
INSERT INTO table1 (foo, bar) VALUES (1, 2); -- 正确 INSERT INTO table1 (foo, bar) VALUES (2, 2); -- 正确 INSERT INTO table1 (foo, bar) VALUES (3, 1); -- 正确 INSERT INTO table1 (foo, bar) VALUES (1, 4); -- 失败!
Duplicate entry '1' for key 'ux_table1_foo'
最后一个插入操作失败,因为它违反了对列 foo
上的唯一索引,当试图第二次将值1插入此列时会产生冲突。
在MySQL中,唯一约束允许多个NULL值。
可以在多个列上创建唯一索引。
主键与唯一索引的区别
相同之处:
不同之处:
你可以这样理解:
主键是唯一的
唯一值不一定是元素的表示形式
什么意思?嗯,主键用于标识元素。如果你有一个“人”,你会想要有一个个人身份证号码(社会安全号码或类似的),它是你的“人”身份的主键。
另一方面,这个人可能有一个电子邮件地址是唯一的,但并不能确定这个人的身份。
我总是在关系表中使用主键(中间表/连接表),为什么呢?因为我喜欢在编码时遵循标准,如果“人”有一个标识符,汽车也有一个标识符,那么“人”->“汽车”也应该有一个标识符!
外键与唯一约束和主键一样相互配合。引用自Books Online:
一个FOREIGN KEY约束不必仅与另一张表的PRIMARY KEY约束相连;它也可以被定义为引用另一张表中的UNIQUE约束的列。
对于事务复制,您需要主键。引用自Books Online:
为事务复制发布的表必须有一个主键。如果一张表在事务复制出版物中,则不能禁用与主键列相关联的任何索引。这些索引是由复制所需的。要禁用索引,必须首先从出版物中删除该表。
两个答案都适用于SQL Server 2005。
何时使用代理主键而不是自然键的选择很棘手。类似“始终”或“从不”的答案很少有用。我发现这取决于情况。
举个例子,下面是我的一些表:
CREATE TABLE toll_booths (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
...
UNIQUE(name)
)
CREATE TABLE cars (
vin VARCHAR(17) NOT NULL PRIMARY KEY,
license_plate VARCHAR(10) NOT NULL,
...
UNIQUE(license_plate)
)
CREATE TABLE drive_through (
id INTEGER NOT NULL PRIMARY KEY,
toll_booth_id INTEGER NOT NULL REFERENCES toll_booths(id),
vin VARCHAR(17) NOT NULL REFERENCES cars(vin),
at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
amount NUMERIC(10,4) NOT NULL,
...
UNIQUE(toll_booth_id, vin)
)
相对于唯一索引,聚集索引存在一些缺点。
如前所述,聚集索引会在表中物理排序数据。
这意味着当你在一个包含聚集索引的表上进行大量插入或删除时,每次(好吧,几乎每次,取决于你的填充因子)更改数据时,物理表都需要更新以保持排序。
在相对较小的表中,这很好,但是当涉及到具有GB级别数据且插入/删除影响排序的表时,你将遇到问题。