当前位置: 首页 > news >正文

第3节-使用表格数据-CHECK约束

摘要: 在本教程中,你将学习如何使用 PostgreSQLCHECK 约束来确保表列中的值满足某个条件。

PostgreSQL CHECK 约束简介

PostgreSQLCHECK 约束通过确保列中的值必须满足布尔表达式来维护数据完整性。

当列具有 CHECK 约束时,如果您尝试插入或更新导致布尔表达式为 false 的值,PostgreSQL 会发出约束冲突并拒绝这些更改。

CHECK 约束有助于在数据库级别实施数据完整性规则。它们可以防止向表列中插入或更新无效数据。

例如,你可以使用 CHECK 约束来防止向 price 列或 products 表中插入负值。

以下是 CHECK 约束的语法:

CREATE TABLE table_name (column1 data_type CONSTRAINT constraint_name CHECK(boolean_expression),...);

在此语法中:

  • 首先,向表列添加一个 CHECK 约束。
  • 其次,在 CONSTRAINT 关键字后提供一个约束名称。如果发生约束违反错误,该约束名称将在错误信息中显示。如果不提供约束名称,PostgreSQL 会为该约束隐式生成一个名称。
  • 第三,在 CHECK 关键字后面的括号()中放入一个布尔表达式,用于检查要插入或更新到列中的值。该布尔表达式可以引用同一张表的列,而不能引用其他表的列。

以下是不使用约束名称的更简洁语法:

CREATE TABLE table_name (column1 data_type CHECK(boolean_expression),...
);

这个 CHECK 约束是列约束,因为它附加到特定的列 (column1)

值得注意的是,您可以对同一列应用多个约束。例如,您可以对同一列同时使用 NOT NULLCHECK 约束:

CREATE TABLE table_name (column1 data_type NOT NULL CHECK(boolean_expression),...
);

或者,您可以将 CHECK 约束定义为表约束:

CREATE TABLE table_name (column1 data_type NOT NULL,...,CHECK(boolean_expression)
);

在这种语法中,您要在列列表之后定义 CHECK 约束。当在布尔表达式中引用多个表列时,这种语法很方便。

基本的 PostgreSQL CHECK 约束示例

首先,创建一个表,名为 products ,并添加一个 CHECK 约束,以确保价格大于或等于0:

CREATE TABLE products (product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,name VARCHAR(255) NOT NULL,price DEC(11, 2) NOT NULL CONSTRAINT positive_price CHECK (price >= 0),discounted_price DEC(11, 2) NOT NULL DEFAULT 0
);

接下来,尝试向 products 表中插入一行包含负价格的数据:

INSERT INTOproducts (name, price)
VALUES('iPhone Pro 15', -1299.99);

PostgreSQL 发出了以下错误:

new row for relation "products" violates check constraint "positive_price"

然后,插入一行包含有效价格的新记录:

INSERT INTOproducts (name, price)
VALUES('iPhone Pro 15', 1299.99) RETURNING *;

输出:

 product_id |     name      |  price  | discounted_price
------------+---------------+---------+------------------2 | iPhone Pro 15 | 1299.99 |             0.00

之后,将价格更新为无效值:

UPDATE products
SETprice = -899.99
WHEREproduct_id = 2;

PostgreSQL 发出了相同的检查约束冲突:

new row for relation "products" violates check constraint "positive_price"

最后,将价格更新为有效的价格:

UPDATE products
SETprice = 999.99
WHEREproduct_id = 2 
RETURNING *;

输出:

 product_id |     name      | price  | discounted_price
------------+---------------+--------+------------------2 | iPhone Pro 15 | 999.99 |             0.00

输出表明该语句已成功更新产品价格。

为表添加 CHECK 约束

您可以使用 ALTER TABLE ... ADD CONSTRAINT 语句向现有表添加 CHECK 约束。

以下是该语句的语法:

ALTER TABLE table_name 
ADD CONSTRAINT constraint_name 
CHECK (boolean_expression)

例如,以下语句添加了一个 CHECK 约束,用于检查折扣价是否低于原价:

ALTER TABLE products
ADD CONSTRAINT discounted_price_check
CHECK (discounted_price < price AND discounted_price > 0);

PostgreSQL 会发出错误,因为表中的某些行违反了新的 CHECK 约束:

check constraint "discounted_price_check" of relation "products" is violated by some row

原因是行 ID 2 的折扣价为 0 ,这违反了新的 CHECK 约束。

要解决此问题,你可以更新现有行的折扣价格,使其符合新的 CHECK 约束:

UPDATE products
SET discounted_price = price * 0.9
RETURNING *;

输出:

 product_id |     name      | price  | discounted_price
------------+---------------+--------+------------------2 | iPhone Pro 15 | 999.99 |           899.99

然后再次向 products 表添加 CHECK 约束:

ALTER TABLE products
ADD CONSTRAINT discounted_price_check
CHECK (discounted_price < price AND discounted_price > 0);

如果您尝试插入一行数据,其中折扣价高于或等于原价,PostgreSQL 会发出检查违规提示。例如:

INSERT INTO products(name, price, discounted_price)
VALUES('iPhone Pro 15', 1299.99, 1399.99);

错误:

ERROR: new row for relation "products" violates check constraint "discounted_price_check"

从表中删除 CHECK 约束

要从表中删除 CHECK 约束,需使用 ALTER TABLE ... DROP CONSTRAINT 语句:

ALTER TABLE table_name
DROP CONSTRAINT IF EXISTS constraint_name;

在此语法中:

  • 首先,指定你要从中移除 CHECK 约束的表名。
  • 其次,在 DROP CONSTRAINT 子句中提供要删除的约束名称。
  • 第三,使用可选的 IF EXISTS 选项,以防止因尝试删除不存在的 CHECK 约束而出现错误。

例如,以下语句会从 products 表中删除 discounted_priceCHECK 约束:

ALTER TABLE products
DROP CONSTRAINT IF EXISTS discounted_price_check;

结论

  • CHECK 约束向表中的一个或多个列添加验证逻辑,以确保数据完整性。
  • 使用 CONSTRAINT ... CHECK 为表定义一个 CHECK 约束。
  • 使用 ALTER TABLE ... ADD CONSTRAINT 语句向表中添加 CHECK 约束。
  • 使用 ALTER TABLE ... DROP CONSTRAINT 语句从表中删除 CHECK 约束。
http://www.dtcms.com/a/379508.html

相关文章:

  • 彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)
  • 【观察】傅建平:迈向“数据强国”,打通数据要素化“任督二脉”的三把钥匙
  • 一些常用的CAPL小功能
  • 当Claude Code失灵,Qwen Code能否成为你的救星?
  • Spring 项目骨架
  • C++轻量级配置管理器升级版
  • WiFi CSI标准
  • 9、从水果店账本到AI大脑:矩阵运算如何驱动现代人工智能?零基础完全指南(Transformer数学原理)
  • 外部碎片和内部碎片
  • Product Hunt 每日热榜 | 2025-09-11
  • 【前沿技术拓展Trip Two】具身智能
  • LeetCode 1658. 将x减到0的最小操作数
  • 二十二、包管理与发布 (Cargo 进阶)
  • WAF如何为你的网站筑起智能防线?
  • 【Leetcode】高频SQL基础题--1327.列出指定时间段内所有的下单产品
  • 数据结构与算法:绪论和线性表
  • ToDesk企业版高效助力睿尔博汽车信息服务!
  • 基于RFID技术的宠物自动喂食器方案
  • Java 异常体系全解析
  • Linux 系统资源负载控制脚本:CPU 内存一键管理(后台常驻版)
  • rook-ceph登录报错Invalid credentials
  • 《RocketMQ核心架构与实战解析》
  • C语言---常量
  • 豆包・图像创作模型 Seedream 4.0 正式发布!
  • OCSP(Online Certificate Status Protocol,在线证书状态协议)
  • 深度学习(六):代价函数的意义
  • 【lite.ai.toolkit】【深度学习】【Ubuntu 20.04】C++ 轻量级AI模型工具箱的编译、安装、使用教程
  • 远程创意协作新方式:cpolar助力Drawnix跨地域团队协作
  • 深入理解 Linux 内核进程管理
  • 企业跨区域组网新解:SD-WAN技术打造安全稳定网络体系