主键约束、唯一性约束、唯一性索引的区别
<p>今天我们一起来理一理数据库中保证数据 <strong>唯一性</strong> 的三种机制,它们分别是 主键约束(Primary Key Constraint)、唯一性约束(Unique Constraint)、唯一性索引(Unique Index)。</p><h3>一、主键约束(Primary Key Constraint)</h3>
<p><strong>1、定义:</strong>主键约束是表中用于 <strong>唯一标识每条记录</strong> 的约束,通过一列或多列(复合主键)的组合,确保表中不存在两条完全相同的记录,且 <strong>不允许空值(NULL)</strong>。</p>
<p><strong>2、核心特性:</strong></p>
<ul>
<li><strong>唯一性:</strong>主键列(或列组合)的值必须唯一,不能重复。</li>
<li><strong>非空性:</strong>主键列的值绝对不允许为 NULL(所有列都不能空)。</li>
<li><strong>标识性:</strong>是表的 "唯一身份证",用于明确区分每条记录,通常作为其他表的外键引用的目标(如订单表的user_id引用用户表的主键id)。</li>
<li><strong>自动关联索引:</strong>数据库会自动为 - <strong>primary key</strong> 创建唯一索引(多数数据库默认是聚集索引,如 SQL Server;Oracle 默认是非聚集索引),以高效维护唯一性。关于 <strong>聚集索引与非聚集索引</strong>,大家可以看下这篇文章 聚集索引与非聚集索引的区别。</li>
</ul>
<p><strong>3、示例:</strong></p>
<pre class="language-sql highlighter-hljs"><code>CREATE TABLE user (
id INT PRIMARY KEY, -- 主键
name VARCHAR(50)
);</code></pre>
<h3>二、唯一性约束(Unique Constraint)</h3>
<p><strong>1、定义:</strong>唯一性约束是用于保证表中 <strong>指定列(或列组合)的值在全表范围内唯一 </strong>的约束,主要用于业务逻辑上的唯一性要求(比如 "身份证号不重复")。</p>
<p><strong>2、核心特性:</strong></p>
<ul>
<li><strong>唯一性:</strong>约束列(或列组合)的值必须唯一,不能重复。</li>
<li><strong>允许空值:</strong>允许列值为 NULL,且 <strong>允许多个 NULL</strong>(因为 NULL 不等于任何值,包括自身,所以多个 NULL 不违反唯一性)。</li>
<li><strong>业务性:</strong>不用于标识记录,仅用于保证业务规则(比如 "一个用户只能有一个身份证号")。</li>
<li><strong>自动关联索引:</strong>数据库会 <strong>自动为 unique constraint 创建唯一索引</strong>(默认是非聚集索引),以高效检查唯一性。</li>
</ul>
<p><strong>3、示例:</strong></p>
<pre class="language-sql highlighter-hljs"><code>CREATE TABLE user (
id INT PRIMARY KEY, -- 主键
id_card VARCHAR(100) UNIQUE -- 唯一约束
);</code></pre>
<h3>三、唯一性索引(Unique Index)</h3>
<p><strong>1、定义:</strong>唯一性索引是一种 <strong>物理存储结构</strong>,通过对指定列(或列组合)创建索引,强制该列值唯一,同时 <strong>加速基于该列的查询</strong>(如<code>WHERE</code>条件过滤、<code>JOIN</code>关联)。</p>
<p><strong>2、核心特性:</strong></p>
<ul>
<li><strong>唯一性</strong>:索引列(或列组合)的值必须唯一,不能重复。</li>
<li><strong>允许空值</strong>:同唯一性约束,允许列值为 NULL,且允许多个 NULL。</li>
<li><strong>性能导向</strong>:核心作用是 <strong>优化查询速度</strong>(减少数据扫描范围),"唯一性" 是附加特性。</li>
<li><strong>手动创建</strong>:需要显式通过 <code><strong>CREATE UNIQUE INDEX</strong> </code>语句创建,不依赖约束存在。</li>
</ul>
<p><strong>3、示例:</strong></p>
<pre class="language-sql highlighter-hljs"><code>CREATE UNIQUE INDEX idx_id_card ON user(id_card); -- 唯一索引</code></pre>
<h3>对比表格</h3>
<table>
<thead>
<tr>
<th>维度</th>
<th>主键约束(Primary Key)</th>
<th>唯一性约束(Unique Constraint)</th>
<th>唯一性索引(Unique Index)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>约束类型</strong></td>
<td>逻辑约束(数据完整性规则)</td>
<td>逻辑约束(数据完整性规则)</td>
<td>物理结构(索引,优化查询)</td>
</tr>
<tr>
<td><strong>空值允许</strong></td>
<td>不允许任何列为 NULL</td>
<td>允许列值为 NULL(允许多个)</td>
<td>允许列值为 NULL(允许多个)</td>
</tr>
<tr>
<td><strong>数量限制</strong></td>
<td>一个表只能有 1 个主键(可复合)</td>
<td>一个表可以有多个唯一性约束</td>
<td>一个表可以有多个唯一性索引</td>
</tr>
<tr>
<td><strong>与索引的关系</strong></td>
<td>自动创建唯一索引(不可单独删除)</td>
<td>自动创建唯一索引(不可单独删除)</td>
<td>本身就是索引(可单独创建 / 删除)</td>
</tr>
<tr>
<td><strong>作用核心</strong></td>
<td>标识记录(表的 "身份证")</td>
<td>保证业务唯一性(如邮箱不重复)</td>
<td>提升查询性能(附带唯一性)</td>
</tr>
<tr>
<td><strong>外键引用目标</strong></td>
<td>可被其他表的外键引用</td>
<td>通常不被外键引用(语义不适合)</td>
<td>不能被外键引用(不是约束)</td>
</tr>
<tr>
<td><strong>删除影响</strong></td>
<td>删除主键约束,自动索引会被删除</td>
<td>删除唯一性约束,自动索引会被删除</td>
<td>删除索引,不影响约束(若存在)</td>
</tr>
</tbody>
</table>
<h3>总结</h3>
<ul>
<li><strong>主键约束</strong>:唯一标识记录,非空,表中唯一,是表的 "核心身份标识"。</li>
<li><strong>唯一性约束</strong>:保证业务字段唯一,允许空,可多个,是 "业务规则的守护者"。</li>
<li><strong>唯一性索引</strong>:优化查询速度,附带唯一性,可多个,是 "性能优化工具"。</li>
</ul>
<p style="text-align: right"><span style="color: rgba(53, 152, 219, 1)">世上没有完美的人,也没有完美的事。-- 烟沙九洲</span></p>
<p><span data-cke-copybin-end="1"></span></p><br><br>
来源:https://www.cnblogs.com/yanshajiuzhou/p/19036908
頁:
[1]