许多数据库管理员(DBA)需要至少花费一段时间来尝试从数据库表中识别和删除重复记录。如果一开始多注意防止重复插入,那么识别和删除重复记录所花费的大部分时间都可以用于其他工作上。原则上,这并不难做到。但是,实际上,你可能甚至不知道有重复的行!今天的文章将会介绍一些策略,通过防止将重复记录插入数据库表中来减少重复记录的发生。
使用主键和唯一键索引
为确保表中的行是唯一的,必须限制一个或多个列以拒绝非唯一值。满足此要求,可以使用表的任何唯一标识符快速检索表中的任何行。我们可以通过在适用的字段中包含主键或主键索引来强制列的唯一性。
为了说明这一点,让我们看一个包含产品详细信息的表,例如名、系列、供应商、描述等。以下是它在 Navicat 表设计器中的样子:
Navicat 使用“键”标题下的钥匙图标指示作为键一部分的字段,并用数字表示其在组合键中的位置。带有数字 1 的单个钥匙图标告诉我们 productCode是表的唯一主键(PK)列。根据定义,主键必须是唯一的,并且不能包含 NULL 值。
同时,如果我们再看一下「索引」选项卡,它表明已为 productLine 列进行索引:
在许多情况下,单一列不足以使一行成为唯一,因此我们必须在主键中添加其他字段。以下是一个需要同时使用 customerNumber 和 checkNumber 作为唯一主键的 payments 表,因为同一位客户可以进行多次付款:
自动递增主键的缺点
许多数据库设计人员或开发人员(包括我自己!)喜欢使用数字自动递增主键,因为:
- 易于使用。数据库会负责它们!
- 因为每个新行都接收一个唯一的整数,所以冲突是不可能的。
以下就是一个这样的表:
在 Navicat 中,创建自动递增的主键所需要做的就是选择数字数据类型(例如整数)并勾选「动递增」框。数据库将会为该列生成所有值。
现在是坏消息,自动递增的主键对防止重复行几乎没有作用,特别是如果你不包含任何其他表索引。例如,假设表没有任何额外的索引。这就没有什么可以阻止某人插入与现有行具有完全相同的 first_name 和 last_name 的行。
实际上,我们现在可以检验该理论!在 Navicat 中,我们可以通过点击加号(+)按钮将新行直接插入到网格中:
正如预期的那样(害怕),重复的名已被接受!
总结
今天的故事值得注意的是,尽管有方法可以防止插入重复的行,但这并不一定意味着可以防止所有数据重复。至少,设计人员或开发人员必须采取其他预防措施,要么在数据库设计中采用严格的规范化,要么在应用程序级别执行特定的验证。