跳到主要内容

约束

在 SQL 中,可以为表定义约束。约束会对插入表的数据施加特定规则。约束可作为表 schema 的一部分,在 CREATE TABLE 语句中声明。某些情况下也可通过 ALTER TABLE 语句后续添加约束,但目前并非所有约束都支持这种方式。

警告:约束会显著影响性能:会降低加载和更新速度,但会加速部分查询。详情请参阅性能指南

语法

CHECK 约束

CHECK 约束允许你指定任意布尔表达式。凡是不满足该表达式的数据都违反约束。例如可通过如下 CHECK 约束强制 name 列不能包含空格。

CREATE TABLE students (name VARCHAR CHECK (NOT contains(name, ' ')));
INSERT INTO students VALUES ('this name contains spaces');
Constraint Error:
CHECK constraint failed on table students with expression CHECK((NOT contains("name", ' ')))

NOT NULL 约束

NOT NULL 约束表示该列不能包含 NULL。默认情况下,表中所有列都可为空。为列定义添加 NOT NULL 后即可强制该列不可为 NULL

CREATE TABLE students (name VARCHAR NOT NULL);
INSERT INTO students VALUES (NULL);
Constraint Error:
NOT NULL constraint failed: students.name

PRIMARY KEY 与 UNIQUE 约束

PRIMARY KEY 或 UNIQUE 约束用于定义能唯一标识表中一行的一列或多列。该约束保证指定列在表内唯一,即同一组值最多只能出现一行。

CREATE TABLE students (id INTEGER PRIMARY KEY, name VARCHAR);
INSERT INTO students VALUES (1, 'Student 1');
INSERT INTO students VALUES (1, 'Student 2');
Constraint Error:
Duplicate key "id: 1" violates primary key constraint
CREATE TABLE students (id INTEGER, name VARCHAR, PRIMARY KEY (id, name));
INSERT INTO students VALUES (1, 'Student 1');
INSERT INTO students VALUES (1, 'Student 2');
INSERT INTO students VALUES (1, 'Student 1');
Constraint Error:
Duplicate key "id: 1, name: Student 1" violates primary key constraint

为高效保证该属性,表中每个 PRIMARY KEY 或 UNIQUE 约束都会自动创建 ART 索引

PRIMARY KEY 与 UNIQUE 约束的差异仅有两点:

  • 一个表只能有一个 PRIMARY KEY 约束,但可以有多个 UNIQUE 约束
  • PRIMARY KEY 还会强制键值不能为 NULL
CREATE TABLE students (id INTEGER PRIMARY KEY, name VARCHAR, email VARCHAR UNIQUE);
INSERT INTO students VALUES (1, 'Student 1', 'student1@uni.com');
INSERT INTO students VALUES (2, 'Student 2', 'student1@uni.com');
Constraint Error:
Duplicate key "email: student1@uni.com" violates unique constraint.
INSERT INTO students (id, name) VALUES (3, 'Student 3');
INSERT INTO students (name, email) VALUES ('Student 3', 'student3@uni.com');
Constraint Error:
NOT NULL constraint failed: students.id

警告:索引存在一些限制,可能导致约束检查过于激进,从而出现 violates primary key constraintviolates unique constraint 等错误。详情见indexes 章节

你也可以在多列上定义唯一性约束:

CREATE TABLE integers (i INTEGER, j INTEGER, k INTEGER, UNIQUE (i, j));
INSERT INTO integers VALUES (1, 2, 3);
INSERT INTO integers VALUES (1, 4, 5);
INSERT INTO integers VALUES (1, 2, 5);
Constraint Error:
Duplicate key "i: 1, j: 2" violates unique constraint.

FOREIGN KEY 约束

FOREIGN KEY 用于定义引用另一张表 PRIMARY KEY 或 UNIQUE 约束的一列或多列。该约束要求被引用键必须在另一表中存在。

CREATE TABLE students (id INTEGER PRIMARY KEY, name VARCHAR);
CREATE TABLE subjects (id INTEGER PRIMARY KEY, name VARCHAR);
CREATE TABLE exams (
exam_id INTEGER PRIMARY KEY,
subject_id INTEGER REFERENCES subjects(id),
student_id INTEGER REFERENCES students(id),
grade INTEGER
);
INSERT INTO students VALUES (1, 'Student 1');
INSERT INTO subjects VALUES (1, 'CS 101');
INSERT INTO exams VALUES (1, 1, 1, 10);
INSERT INTO exams VALUES (2, 1, 2, 10);
Constraint Error:
Violates foreign key constraint because key "id: 2" does not exist in the referenced table

为高效保证该属性,表中每个 FOREIGN KEY 约束也会自动创建 ART 索引

警告:索引存在一些限制,可能导致约束检查过于激进,从而出现 violates primary key constraintviolates unique constraint 等错误。详情见indexes 章节