PostgreSQL 教程: CHECK 约束

九月 13, 2023

摘要:在本教程中,您将了解 PostgreSQL 的CHECK约束以及如何使用它们基于布尔表达式来约束表列中的值。

CHECK约束是一种约束,允许您指定列中的值是否必须满足特定要求。

在将值插入或更新到列之前,CHECK约束使用布尔表达式来计算值。

如果这些值通过检查,PostgreSQL 会将这些值插入更新到该列。否则,PostgreSQL 将拒绝更改并发出约束违规错误。

为新表定义 CHECK 约束

通常,您在使用CREATE TABLE语句创建表时使用CHECK约束。

以下语句定义一个employees表。

DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
	id SERIAL PRIMARY KEY,
	first_name VARCHAR (50),
	last_name VARCHAR (50),
	birth_date DATE CHECK (birth_date > '1900-01-01'),
	joined_date DATE CHECK (joined_date > birth_date),
	salary numeric CHECK(salary > 0)
);

employees表具有三个CHECK约束:

  • 首先,员工的出生日期 (birth_date) 必须大于01/01/1900。如果您尝试插入在01/01/1900之前的出生日期,您将收到一条错误消息。
  • 其次,加入日期 (joined_date) 必须大于出生日期 ( birth_date)。此检查将防止更新语义上无效的日期。
  • 第三,工资必须大于零,这是显而易见的。

让我们尝试向employees表中插入一个新行:

INSERT INTO employees (first_name, last_name, birth_date, joined_date, salary)
VALUES ('John', 'Doe', '1972-01-01', '2015-07-01', - 100000);

该语句试图在salary列中插入负工资。但是,PostgreSQL 返回了以下错误消息:

ERROR:  new row for relation "employees" violates check constraint "employees_salary_check"
DETAIL:  Failing row contains (1, John, Doe, 1972-01-01, 2015-07-01, -100000).

由于salary列上的CHECK约束仅接受正值,插入失败。

默认情况下,PostgreSQL 使用以下模式为CHECK约束命名:

{table}_{column}_check

例如,工资列的约束具有以下约束名称:

employees_salary_check

但是,如果要为CHECK约束指定特定名称,可以在CONSTRAINT表达式后面指定,如下所示:

column_name data_type CONSTRAINT constraint_name CHECK(...)

请参见以下示例:

...
salary numeric CONSTRAINT positive_salary CHECK(salary > 0)
...

为现有表定义 CHECK 约束

要向现有表添加CHECK约束,请使用ALTER TABLE语句。假设数据库中有一个名为prices_list的现有表:

CREATE TABLE prices_list (
	id serial PRIMARY KEY,
	product_id INT NOT NULL,
	price NUMERIC NOT NULL,
	discount NUMERIC NOT NULL,
	valid_from DATE NOT NULL,
	valid_to DATE NOT NULL
);

现在,您可以使用ALTER TABLE语句将CHECK约束添加到prices_list表中。价格和折扣必须大于零且折扣小于价格。请注意,我们使用包含AND运算符的布尔表达式。

ALTER TABLE prices_list 
ADD CONSTRAINT price_discount_check 
CHECK (
	price > 0
	AND discount >= 0
	AND price > discount
);

失效日期 (valid_to) 必须大等于生效日期 (valid_from) 。

ALTER TABLE prices_list 
ADD CONSTRAINT valid_range_check 
CHECK (valid_to >= valid_from);

这些CHECK约束对于放置额外的逻辑来限制列在数据库层可以接受的值非常有用。通过使用CHECK约束,您可以确保数据正确更新到数据库。

在本教程中,您学习了如何使用 PostgreSQL 的CHECK约束基于布尔表达式检查列的值。