SQL键类型详解:超键到外键全解析

在 SQL 中,键(Key)是数据库设计的核心要素,用于确保数据完整性、建立表间关系和优化查询效率。以下从特性、作用、使用场景、创建方式及示例五个维度,详细解析常见的键类型:

一、超键(Super Key)

特性
  • 由一个或多个列组成的集合,能唯一标识表中的一条记录
  • 允许包含冗余列(即删除部分列后,剩余部分仍可能是超键)。
  • 一个表可以有多个超键,且超键之间可能存在包含关系。
作用
  • 基础标识作用,是候选键、主键的 "前身"(候选键是最小超键)。
使用场景
  • 主要用于数据库设计的理论分析阶段,实际建表时很少直接定义超键(更多使用其简化形式 ------ 候选键或主键)。
示例

假设有学生表 students,包含列 学号(id)、姓名(name)、身份证号(id_card)

  • (id) 是超键(可唯一标识学生)。
  • (id, name) 是超键(id 已能唯一标识,name 是冗余列)。
  • (id_card, name) 是超键(id_card 唯一,name 冗余)。

二、候选键(Candidate Key)

特性
  • 最小的超键(删除任何一个列后,就不再能唯一标识记录)。
  • 不包含冗余列,值唯一且非 NULL(与主键要求一致)。
  • 一个表可以有多个候选键(称为 "复合候选键" 时由多列组成)。
作用
  • 作为主键的候选者,提供了表中记录的 "备用唯一标识"。
  • 保证数据唯一性,是设计主键的基础。
使用场景
  • 表中存在多个可唯一标识记录的列时(如 "学生表" 的学号和身份证号)。
  • 为后续主键选择提供灵活的备选方案。
示例

学生表 students 中:

  • id 唯一且非空,则 id 是候选键。
  • id_card 唯一且非空,则 id_card 也是候选键。
  • 此时 idid_card 均为候选键,可从中选择一个作为主键。

三、主键(Primary Key, PK)

特性
  • 从候选键中人为选定的唯一标识 ,一个表只能有一个主键
  • 主键列不允许为 NULL ,且值绝对唯一(无重复)。
  • 通常自动创建索引(主键索引),可大幅提升查询效率。
作用
  • 唯一标识表中的每条记录,避免数据重复。
  • 作为表与表之间关联的 "锚点"(外键通常关联主键)。
  • 通过主键索引加速查询(尤其是按主键过滤或排序时)。
使用场景
  • 所有表都应定义主键(除非特殊情况,如日志表等无唯一标识的表)。
  • 需唯一区分记录的场景(如用户表的user_id、订单表的order_id)。
创建方式
  1. 建表时定义(最常用):
sql 复制代码
CREATE TABLE users (
  user_id INT PRIMARY KEY,  -- 单列主键
  username VARCHAR(50) NOT NULL,
  email VARCHAR(100)
);

2.复合主键(多列组合作为主键):

sql 复制代码
-- 课程学生关联表(一个学生可选多门课,一门课有多个学生)
CREATE TABLE student_course (
  student_id INT,
  course_id INT,
  PRIMARY KEY (student_id, course_id)  -- 复合主键,确保(学生,课程)组合唯一
);

3.建表后添加主键(需确保列非空且唯一):

sql 复制代码
CREATE TABLE products (
  product_id INT,
  product_name VARCHAR(100)
);
-- 后续添加主键
ALTER TABLE products 
ADD PRIMARY KEY (product_id);

四、外键(Foreign Key, FK)

特性
  • 用于关联两个表的列(或列组合),其值需匹配另一个表的主键或唯一键
  • 所在表称为 "子表",被关联的表称为 "父表"。
  • 外键值可以为 NULL(表示该记录未关联父表数据),但非 NULL 时必须在父表中存在(除非设置级联操作)。
作用
  • 建立表之间的参照完整性 (如 "订单表" 的user_id必须对应 "用户表" 中存在的user_id)。
  • 定义表间关系(一对一、一对多、多对多),是关系型数据库的核心特性。
使用场景
  • 存在关联关系的表(如 "订单表" 与 "用户表"、"学生表" 与 "班级表")。
  • 需限制子表数据必须依赖父表存在的场景(如不允许存在 "不存在的用户" 的订单)。
创建方式
  1. 建表时定义外键
sql 复制代码
-- 父表(班级表)
CREATE TABLE classes (
  class_id INT PRIMARY KEY,
  class_name VARCHAR(50) NOT NULL
);

-- 子表(学生表),外键关联班级表的class_id
CREATE TABLE students (
  student_id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  class_id INT,  -- 外键列
  -- 定义外键:引用父表的主键
  FOREIGN KEY (class_id) REFERENCES classes(class_id)
    ON DELETE SET NULL  -- 父表记录删除时,子表外键设为NULL
    ON UPDATE CASCADE   -- 父表主键更新时,子表外键同步更新
);
  • ON DELETE/ON UPDATE 是级联操作,可选值:RESTRICT(禁止删除 / 更新,默认)、CASCADE(级联删除 / 更新)、SET NULL(设为 NULL)等。

2.建表后添加外键

sql 复制代码
ALTER TABLE students
ADD FOREIGN KEY (class_id) 
REFERENCES classes(class_id);

五、唯一键(Unique Key)

特性
  • 保证列(或列组合)的值唯一 ,但与主键的区别:
    • 一个表可以有多个唯一键(主键只能有一个)。
    • 唯一键允许列值为NULL(但最多只能有一个 NULL,因 SQL 中 NULL≠NULL)。
  • 会自动创建唯一索引,提升查询效率(类似主键索引)。
作用
  • 约束非主键列的唯一性(如用户表的 "手机号""邮箱")。
  • 作为外键的关联目标(主键也可,但唯一键更灵活)。
使用场景
  • 需要唯一但不作为主键的列(如 "用户表" 的phone,需唯一但主键用user_id)。
  • 多列组合唯一的场景(如 "文章表" 的(title, author)组合不重复)。
创建方式
  1. 建表时定义
sql 复制代码
CREATE TABLE users (
  user_id INT PRIMARY KEY,
  email VARCHAR(100) UNIQUE,  -- 唯一键:邮箱不重复
  phone VARCHAR(20) UNIQUE,   -- 另一个唯一键:手机号不重复
  username VARCHAR(50)
);

2.复合唯一键(多列组合唯一):

sql 复制代码
CREATE TABLE articles (
  article_id INT PRIMARY KEY,
  title VARCHAR(200),
  author_id INT,
  -- 标题+作者组合唯一(避免同一作者重复发同标题文章)
  UNIQUE KEY unique_title_author (title, author_id)
);

3.建表后添加唯一键

sql 复制代码
ALTER TABLE users
ADD UNIQUE (email);  -- 为email添加唯一键

总结对比表

|-----|-----|---------|------|---------------|-------------------|
| 键类型 | 唯一性 | 允许 NULL | 数量限制 | 核心作用 | 典型场景 |
| 超键 | 是 | 允许 | 多个 | 理论上的唯一标识(含冗余) | 数据库设计分析阶段 |
| 候选键 | 是 | 不允许 | 多个 | 主键的候选(无冗余) | 提供唯一标识备选方案 |
| 主键 | 是 | 不允许 | 1 个 | 表的主标识,关联基础 | 所有表的唯一记录标识 |
| 外键 | 否 | 允许 | 多个 | 建立表间关联,保证参照完整 | 订单 - 用户、学生 - 班级关联 |
| 唯一键 | 是 | 允许 | 多个 | 约束非主键列的唯一性 | 邮箱、手机号等唯一但非主键列 |

相关推荐
E***U94517 小时前
MySQL自然语言处理应用
数据库·mysql
洛_尘18 小时前
MySQL 2:库的操作
数据库·mysql
码农101号18 小时前
Linux - 达梦数据库的安装
数据库
l1t18 小时前
使用DuckDB SQL求解Advent of Code 2024第9题 磁盘碎片整理
数据库·sql·算法·duckdb·advent of code
Z***u65918 小时前
MySQL物联网开发
数据库·mysql
Wang's Blog19 小时前
MongoDB小课堂: 容器化部署与操作综合指南
数据库·mongodb
IT小哥哥呀19 小时前
从零到NoSQL:一个动手的MongoDB教程(无需安装!)
数据库·mongodb·nosql·教程·初学者
J***793919 小时前
MySQL语音识别案例
数据库·mysql·语音识别
y***866919 小时前
MySQL语音识别开发
数据库·mysql·语音识别
大任视点19 小时前
科技赋能健康未来,守护生命青春活力
大数据·人工智能·科技