PostgreSQL 表中可以添加哪些约束?
一般来说,PostgreSQL 表可以使用 6 种类型的约束。它们列出如下并进行了解释:
NOT NULL 约束
这是一个非常常见的约束。如果某个特定列不能包含空值,则在创建表时添加此约束。例如,如果我们创建一个成绩表,该表不允许“姓名”列为空值,则创建表的命令如下所示:
CREATE TABLE marks( name VARCHAR NOT NULL, roll_no INTEGER, marks_obtained INTEGER );
现在,如果我们尝试在不提供“姓名”列值的情况下向此表中插入一行,将会看到错误。让我们尝试一下:
INSERT INTO marks(roll_no, marks_obtained) VALUES(25,56)
您将看到的错误类似于以下内容:
ERROR: null value in column "name" violates not-null constraint DETAIL: Failing row contains (null, 25, 56). SQL state: 23502
UNIQUE 约束
顾名思义,此约束表示相关列不能包含重复值。这同样也是一个非常常见的约束。如果我们现在创建成绩表并希望在“学号”列上设置 UNIQUE 约束,则可以通过以下方式完成:
CREATE TABLE marks( name VARCHAR, roll_no INTEGER UNIQUE, marks_obtained INTEGER );
现在,如果我们尝试插入重复的学号值,PostgreSQL 将抛出错误。让我们尝试一下:
INSERT INTO marks(name, roll_no, marks_obtained) VALUES('Yash',25,56), ('Isha',25,64)
您将看到的错误类似于以下内容:
ERROR: duplicate key value violates unique constraint "marks_roll_no_key" DETAIL: Key (roll_no)=(25) already exists. SQL state: 23505
PRIMARY KEY 约束
这是 NOT NULL 和 UNIQUE 约束的组合。它可以应用于单个列或多个列。如果 PRIMARY KEY 应用于多个列,则这些列的组合应具有唯一值,而各个列可以有重复的值。
让我们看看在单列和多列上应用 PRIMARY KEY 约束的示例:
单列:
CREATE TABLE marks( name VARCHAR, roll_no INTEGER PRIMARY KEY, marks_obtained INTEGER );
多列:
CREATE TABLE marks( name VARCHAR, roll_no INTEGER, marks_obtained INTEGER, PRIMARY KEY (name, roll_no) );
对于 Primary Key 约束,添加空值或重复值都会导致 PostgreSQL 抛出错误。检查此错误留作读者的练习。
FOREIGN KEY 约束
此约束有助于维护多个表之间的一致性。假设您已经在前面的示例中创建了一个成绩表,其中“学号”是 PRIMARY KEY。现在,如果您要创建另一个名为 student_info 的表,该表也具有“学号”列,并且您希望确保 student_info 表中只允许存在于成绩表中的“学号”值,则您将在 student_info 表的“学号”列上添加 FOREIGN KEY 约束。您可以这样做:
CREATE TABLE student_info( name VARCHAR, roll_no INTEGER REFERENCES marks (roll_no), age INTEGER, gender VARCHAR );
现在,student_info 表的“学号”列引用了成绩表的“学号”列。因此,您将无法在 student_info 中添加任何“学号”不在成绩表中的值。
如果我的成绩表如下所示:
姓名 | 学号 | 百分比成绩 |
---|---|---|
Siddhi | 45 | 65 |
Yash | 26 | 42 |
Isha | 56 | 87 |
那么,我尝试在 student_info 表中添加学号为 45 的值。
INSERT INTO student_info(name, roll_no, age, gender) VALUES ('Siddhi',45,23,'F');
此查询成功,因为学号 45 存在于成绩表中。现在,让我们尝试在 student_info 表中添加学号 12。
INSERT INTO student_info(name, roll_no, age, gender) VALUES ('Aniket',12,26,'M');
PostgreSQL 将在此处抛出错误:
ERROR: insert or update on table "student_info" violates foreign key constraint "student_info_roll_no_fkey" DETAIL: Key (roll_no)=(12) is not present in table "marks". SQL state: 23503
就像我们可以在多列上添加 PRIMARY KEY 约束一样,我们也可以在多列上添加 FOREIGN KEY 约束。下面给出了一个示例:
CREATE TABLE student_info( name VARCHAR, roll_no INTEGER, age INTEGER, gender VARCHAR, FOREIGN KEY (name, roll_no) REFERENCES marks (name, roll_no) );
CHECK 约束
这是一个自定义约束。它允许我们强制列满足布尔表达式。例如,如果我们希望“学号”在成绩表中大于 0,我们可以如下添加该约束:
CREATE TABLE marks( name VARCHAR, roll_no INTEGER CHECK (roll_no > 0), marks_obtained INTEGER );
现在,如果我尝试向此表中添加学号为 0 的条目,我将看到以下错误:
INSERT INTO marks(name, roll_no, marks_obtained) VALUES('Yash',0,25)
ERROR: new row for relation "marks" violates check constraint "marks_roll_no_check" DETAIL: Failing row contains (Yash, 0, 25). SQL state: 23514
EXCLUSION 约束
此约束的解释由 Stack Overflow 的一个答案给出。您可以在此处查看它:https://stackoverflow.com/a/51247705。现在,这是 UNIQUE 约束的更通用的扩展。UNIQUE 表示没有两行可以在相关列中具有相同的值。此约束更进一步。它表示,没有两行应该_______。您可以在空格中填写任何内容。您可以说“没有两行可以不同”,或者“没有两行可以相交”,或者任何其他语句,具体取决于上下文和正在考虑的列。现在,UNIQUE 约束是 EXCLUSION 约束的一个特例。但 UNIQUE 很简单。它只是说没有两行可以相同。因此,我们实际上检查的是 = 运算符。而 = 检查很容易执行。但并非所有运算符检查都一样容易。因此,EXCLUSION 约束要求您在应用约束的列上创建一个索引。这将确保比较速度很快。让我们通过一个示例来理解这一点。
CREATE TABLE marks( name VARCHAR, roll_no INTEGER, marks_obtained INTEGER, EXCLUDE USING gist(roll_no WITH <>) );
请注意,您必须在每个数据库中运行一次 CREATE EXTENSION btree_gist,才能使上述命令正常工作。
现在,<> 是 PostgreSQL 中的不等于运算符。我们实际上告诉 PostgreSQL,对于添加到表的每一行,都使用 NOT EQUAL 运算符检查“学号”与所有其他已存在的“学号”。仅当所有比较结果都为 FALSE 时才允许它。换句话说,只允许所有学号相同,不允许不同的学号。
现在,让我们向上述表中添加一个值:
INSERT INTO marks8(name, roll_no, marks_obtained) VALUES('Yash',26,55)
这将起作用。现在让我们添加另一个具有不同学号的值。
INSERT INTO marks8(name, roll_no, marks_obtained) VALUES('Isha',56,65)
这将抛出一个错误:
ERROR: conflicting key value violates exclusion constraint "marks_roll_no_excl" DETAIL: Key (roll_no)=(56) conflicts with existing key (roll_no)=(26). SQL state: 23P01
如果我想使用 EXCLUSION 强制执行 UNIQUE 约束,我会将 <> 替换为 =。
您也可以在多列上添加 EXCLUDE 约束。此处给出了一个示例:https://tutorialspoint.com/postgresql/postgresql_constraints.htm#:~:text=EXCLUSION%20Constraint。