主键和外键 SQLite 与例子

以下各节将解释 SQLite 详细讲解约束,从定义和连接表的 PRIMARY KEY 和 FOREIGN KEY 开始,涵盖了用于验证每一列数据的 NOT NULL、DEFAULT、UNIQUE 和 CHECK 规则。
SQLite 限制
列约束对插入到列中的值强制执行规则,以验证数据。这些约束在创建表时定义在列定义中。它们通过拒绝违反您设置的规则的值(例如重复值、空值或在相关表中不存在的值)来保持存储数据的一致性和准确性。
SQLite 首要的关键
主键列中的所有值都必须是唯一的且不能为空。主键唯一标识表中的每一行。
主键可以应用于单个列,也可以应用于多个列的组合。如果是后者,则这些列的值的组合对于表中的所有行都应该是唯一的。
语法:
定义表中的主键有几种不同的方法:
在列定义本身中:
ColumnName INTEGER NOT NULL PRIMARY KEY;
作为单独的定义:
PRIMARY KEY(ColumnName);
要创建列组合作为主键:
PRIMARY KEY(ColumnName1, ColumnName2);
SQLite NOT NULL、DEFAULT、UNIQUE 和 CHECK 约束
除了主键之外, SQLite 它提供了多个列约束,用于验证表中输入的值。NOT NULL、DEFAULT、UNIQUE 和 CHECK 约束均在列定义中定义,每个约束都对列强制执行特定的规则。 数据类型 和价值观。
NOT NULL 约束
此 SQLite NOT NULL 约束可以防止列中包含空值:
ColumnName INTEGER NOT NULL;
默认约束
随着 SQLite DEFAULT 约束:如果您未在列中插入任何值,则插入默认值。
例如:
ColumnName INTEGER DEFAULT 0;
如果你编写插入语句但没有为该列指定任何值,则该列的值为 0。
唯一约束
此 SQLite 唯一约束可以防止列中的所有值出现重复值。
例如:
EmployeeId INTEGER NOT NULL UNIQUE;
此规则强制“EmployeeId”值唯一,不允许重复值。请注意,此规则仅适用于“EmployeeId”列的值。
检查约束
此 SQLite CHECK 约束设置一个条件来检查插入的值。如果该值不符合条件,则不会插入。
Quantity INTEGER NOT NULL CHECK(Quantity > 10);
“数量”列中的值不能小于 10。
SQLite 外键
此 SQLite 外键是一种约束,用于验证一个表中存在的值是否在另一个与第一个表有关联的表中存在,该第一个表定义了外键。
在使用多个表时,有时会遇到两个表通过一个共同的列相互关联的情况。如果您希望确保在一个表中插入的值必须存在于另一个表的同一列中,则应该对该共同列使用外键约束。
在这种情况下,当您尝试在该列中插入一个值时,外键将确保插入的值存在于引用表的列中。
请注意,默认情况下未启用外键约束。 SQLite您必须先运行以下命令来启用它们:
PRAGMA foreign_keys = ON;
外键约束于 SQLite 从 3.6.19 版本开始。
示例 SQLite 外键
假设我们有两个表:学生表和院系表。
Students 表包含学生列表,Departments 表包含院系列表。每个学生都属于一个院系;也就是说,每个学生都有一个 departmentId 列。
现在我们将看到外键约束如何帮助确保 Students 表中的部门 ID 值必须存在于 Departments 表中。
因此,如果我们在 Students 表中的 DepartmentId 上创建外键约束,则每个插入的 departmentId 都必须存在于 Departments 表中。
CREATE TABLE [Departments] ( [DepartmentId] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [DepartmentName] NVARCHAR(50) NULL ); CREATE TABLE [Students] ( [StudentId] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, [StudentName] NVARCHAR(50) NULL, [DepartmentId] INTEGER NOT NULL, [DateOfBirth] DATE NULL, FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId) );
为了检查外键约束如何防止将未定义的元素或值插入到与另一个表有关联的表中,我们将研究以下示例。
在这个例子中,“部门”表与“学生”表存在外键关系,因此插入到“学生”表中的任何 departmentId 值都必须存在于“部门”表中。如果您尝试插入一个“部门”表中不存在的 departmentId 值,外键约束将阻止您执行此操作。
让我们在“部门”表中插入两个部门:“IT”和“艺术”,如下所示。 插入查询:
INSERT INTO Departments VALUES(1, 'IT'); INSERT INTO Departments VALUES(2, 'Arts');
这两条语句应该会将两个部门插入到 Departments 表中。之后,您可以运行查询“SELECT * FROM Departments”来确认这两个值是否已插入:
然后尝试插入一个部门 ID 在 Departments 表中不存在的新学生:
INSERT INTO Students(StudentName,DepartmentId) VALUES('John', 5);
该行将不会被插入,并且您会收到一条错误消息,提示:外键约束失败。
主键和外键的区别 SQLite
主键和外键都有助于维护数据完整性,但它们的作用不同。主键用于标识单个表中的行,而外键则连接两个相关表中的行。下表总结了它们的主要区别。
| 基地 | 首要的关键 | 外键 |
|---|---|---|
| 目的 | 唯一标识其自身表中的每一行 | 指的是另一个表的主键,以便将它们链接起来。 |
| 唯一 | 值必须唯一 | 值可以重复,因此多个子行可以共享一个父行。 |
| 空值 | 不能为空 | 当关系为可选关系时,此值可能为空。 |
| 每桌人数 | 每个表只能有一个主键 | 一个表可以有多个外键 |
| 索引 | 自动索引 | 未自动索引;为提高性能,请添加一个。 |
在“学生和部门”示例中,DepartmentId 是“部门”表的主键,也是“学生”表的外键,它将每个学生与一个有效的部门关联起来。
SQLite 复合主键
复合主键是由两列或多列组成的主键。当任何单列本身都不唯一,但各列组合起来对于每一行数据都是唯一的时,可以使用复合主键。 SQLite 将组合后的值视为一个键。
例如,选课表可能允许同一学生选修多门课程,也可能允许同一门课程被多名学生选修,但每个学生-课程组合应该只出现一次:
CREATE TABLE Enrollments ( StudentId INTEGER NOT NULL, CourseId INTEGER NOT NULL, Grade TEXT, PRIMARY KEY (StudentId, CourseId) );
这里,StudentId 和 CourseId 单独都不是唯一的,但 (StudentId, CourseId) 这对键是唯一的,因此同一个学生不能选修同一门课程两次。使用复合键时,请注意以下几点:
- 当单个列无法唯一标识一行时,请使用复合键。
- 复合键中的每一列都遵循主键规则,因此组合值必须是唯一的且不能为空。
- 复合键是作为单独的表级 PRIMARY KEY 子句编写的,而不是写在单个列定义中。
SQLite 外键操作:删除时和更新时
外键还可以控制当其引用的父行被删除或更新时,子行会发生什么情况。这些引用操作是在定义外键时通过 ON DELETE 和 ON UPDATE 子句添加的。 SQLite 支持五项行动:
- 没有行动 — 默认操作,如果子行仍然引用父行,则会引发错误。
- 限制 — 防止在任何其他更改运行之前立即删除或更新。
- 置空 — 将子外键列设置为 null。
- 默认设置 — 将子外键列设置为其声明的默认值。
- CASCADE — 对子行应用相同的更改,因此删除父行也会删除其子行。
以下示例重新创建了 Students 表,以便删除一个部门会自动删除该部门的学生,而更新部门 ID 会更新与之匹配的学生:
CREATE TABLE Students ( StudentId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, StudentName NVARCHAR(50) NULL, DepartmentId INTEGER NOT NULL, FOREIGN KEY(DepartmentId) REFERENCES Departments(DepartmentId) ON DELETE CASCADE ON UPDATE CASCADE );
请记住,引用操作仅在启用外键支持时才会运行,因此请在每次连接开始时运行 `PRAGMA foreign_keys = ON`。否则, SQLite 解析 ON DELETE 和 ON UPDATE 子句,但不强制执行它们。


