当前位置:

首页 > 数据库 > SQL约束有哪些类型及作用

SQL约束有哪些类型及作用

SQLPro
SQLPro

SQLPro 是一款macOS平台上数据库管理应用,避免使用非法,享受更全面的支持和更新。它更贴近日常 macOS 使用场景,处理高频操作时整体会更顺手一些。

立即下载
¥119
macOS 2026-09-24
正版软件 macOS软件 数据库管理工具 macOS

刚开始设计关系型数据库?了解PRIMARY KEY、FOREIGN KEY、UNIQUE、NOT NULL、CHECK、DEFAULT等约束的作用、语法和排错方法。本文以PostgreSQL语法为主,结合用户订单场景,清晰展示如何防止脏数据并处理常见约束冲突。

很多初学者在设计数据库表时,倾向于把所有数据校验逻辑都交给后端代码处理,认为数据库只负责存储。这种想法会导致数据一致性脆弱,一旦应用层出现漏洞或多人同时写入,数据库中就会产生大量脏数据。

SQL 约束(Constraints)是数据库层面的“守门员”,它们在数据写入或更新时自动执行规则,确保数据的完整性、唯一性和有效性。无论应用层如何变化,数据库约束都能保证核心业务规则不被破坏。

先分清约束各自保护什么

在关系型数据库中,最基础的约束主要解决“我是谁”、“我在哪”以及“我不能为空”的问题。我们以常见的 users(用户表)和 orders(订单表)为例。

PRIMARY KEY(主键) 是唯一标识每一行数据的列。它的核心要求是值必须唯一且不能为 NULL。一张表通常只有一个主键,它是其他表引用该表记录的基石。

FOREIGN KEY(外键) 用于建立两张表之间的关联。它保证子表(如 orders)中的某个值(如 user_id)必须在父表(如 users)的主键中存在。这防止了“孤儿记录”的产生,即订单指向了一个不存在的用户。

UNIQUE(唯一约束) 限制一列或多列组合的值不能重复。与主键不同,唯一约束允许值为 NULL(具体行为视数据库而定),且一张表可以有多个唯一约束。例如,用户的邮箱地址通常需要具备唯一性。

NOT NULL(非空约束) 最简单直接,它禁止列中存入 NULL 值。对于必填字段,如用户名或订单金额,必须加上此约束。

下面是一段基于 PostgreSQL 语法的建表语句,展示了这些基础约束的位置:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,          -- 主键:唯一且非空
    username VARCHAR(50) NOT NULL,   -- 非空:用户名必填
    email VARCHAR(100) UNIQUE        -- 唯一:邮箱不能重复
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    -- 外键:user_id 必须存在于 users.id 中
    CONSTRAINT fk_user 
        FOREIGN KEY (user_id) 
        REFERENCES users(id)
);

SQL约束有哪些类型及作用

主键、外键、唯一和非空约束共同保护表数据

在上图中,我们可以直观地看到 users.id 作为主键被 orders.user_id 引用。如果尝试插入一个 user_id 为 999 的订单,而 users 表中没有 id 为 999 的用户,数据库会立即拒绝该操作并抛出外键约束错误。

值域约束:CHECK 与 DEFAULT

除了结构性的关联约束,我们还需要控制数据的具体内容是否符合业务逻辑。这时就需要用到 CHECK 和 DEFAULT 约束。

CHECK 约束 允许你定义一个布尔表达式,只有当表达式结果为真时,数据才能被写入。它常用于限制数值范围或枚举状态。例如,订单状态只能是“待支付”或“已支付”,订单数量必须大于零。

DEFAULT 约束 指定了在插入数据时,如果未提供该列的值,数据库应自动填充的默认值。需要注意的是,DEFAULT 仅在省略该列时生效。如果你显式地插入了 NULL,且该列允许为空,那么存入的就是 NULL,而不是默认值。

以下示例展示了如何在 orders 表中应用这两种约束:

ALTER TABLE orders 
ADD COLUMN status VARCHAR(20) DEFAULT 'pending' 
CHECK (status IN ('pending', 'paid', 'cancelled'));

ALTER TABLE orders 
ADD COLUMN quantity INT DEFAULT 1 
CHECK (quantity > 0);

-- 添加创建时间,默认为当前时间
ALTER TABLE orders 
ADD COLUMN created_at TIMESTAMP DEFAULT NOW();

SQL约束有哪些类型及作用

CHECK 拒绝越界值,DEFAULT 填充省略字段

如图所示,当执行插入操作时:

  1. 如果省略 status 和 created_at,数据库会自动填入 'pending' 和当前时间戳。
  2. 如果尝试插入 quantity = -5,CHECK 约束会拦截该请求,因为 -5 > 0 为假。
  3. 如果显式插入 status = 'shipped',而该值不在 CHECK 允许的列表中,操作同样会失败。

这种机制将业务规则下沉到数据库层,即使后端代码逻辑出错,也能保证数据库中不会出现数量为负数的订单或非法的状态值。

约束组合与跨库差异

在实际工程中,约束往往不是孤立存在的,而是组合使用。同时,不同的数据库管理系统(DBMS)对某些约束的处理细节存在差异,开发时需特别注意。

复合唯一约束

有时单个列无法保证唯一性,需要多列组合。例如,一个用户在同一个日期下只能有一个特定类型的订单。可以使用复合 UNIQUE 约束:

ALTER TABLE orders 
ADD CONSTRAINT unique_user_date_type 
UNIQUE (user_id, order_date, type);

外键的级联行为

当父表记录被删除或更新时,子表该如何反应?可以在定义 FOREIGN KEY 时配置 ON DELETE 和 ON UPDATE 行为:

  • CASCADE:父表删除,子表对应记录也删除。
  • SET NULL:父表删除,子表对应字段设为 NULL(前提是该字段允许为空)。
  • RESTRICT 或 NO ACTION:默认行为,如果子表有引用,则禁止删除父表记录。
CONSTRAINT fk_user 
    FOREIGN KEY (user_id) 
    REFERENCES users(id)
    ON DELETE CASCADE
    ON UPDATE CASCADE;

跨数据库的关键差异

虽然 SQL 标准定义了这些约束,但实现细节有所不同:

  1. UNIQUE 与 NULL:

    • 在 PostgreSQL 和 SQL Server 中,UNIQUE 约束允许有多个 NULL 值,因为 NULL 不等于 NULL。
    • 在 MySQL (InnoDB) 中,行为类似,但需注意旧版本或特定引擎的差异。
    • 在 SQLite 中,UNIQUE 约束通常也允许多个 NULL,但在某些严格模式下可能表现不同。
  2. CHECK 约束的支持:

    • PostgreSQL、SQL Server 和 SQLite 完整支持 CHECK 约束。
    • MySQL 在 8.0.16 之前版本中,虽然解析 CHECK 语法,但会忽略其检查逻辑。如果在老版本 MySQL 上依赖 CHECK 保证数据质量,将会导致数据污染。
  3. 默认表达式:

    • 大多数数据库支持 NOW()、CURRENT_TIMESTAMP 等函数作为默认值。
    • 部分数据库不支持复杂的表达式作为 DEFAULT,仅支持常量或简单函数。

因此,在迁移数据库或编写通用 SQL 时,务必查阅目标数据库的官方文档,特别是关于 CHECK 和 NULL 处理的章节。

遇到约束报错怎么定位

当应用程序抛出“Constraint Violation”或“Integrity Error”时,不要慌张。按照以下步骤可以快速定位问题:

  1. 识别约束名称: 数据库报错信息中通常会包含违反的约束名,如 violates foreign key constraint "fk_user" 或 violates check constraint "orders_quantity_check"。如果没有自定义约束名,数据库会自动生成一个随机名称,此时需查看表定义。

  2. 检查表定义: 使用 \d table_name (PostgreSQL) 或 SHOW CREATE TABLE table_name (MySQL) 查看表的结构,确认哪些列有 NOT NULL、UNIQUE 或 CHECK 限制。

  3. 核对输入数据:

    • NOT NULL 错误:检查是否传入了 NULL 或空字符串,而该列不允许为空。
    • UNIQUE/PRIMARY KEY 错误:检查数据库中是否已存在相同值的记录。
    • FOREIGN KEY 错误:检查引用的父表 ID 是否存在。例如,插入订单前,确认用户 ID 已在 users 表中。
    • CHECK 错误:检查数值是否超出范围,或字符串是否在允许的枚举列表内。
  4. 修正数据或逻辑:

    • 如果是测试数据,清理冲突记录。
    • 如果是业务逻辑问题,需在应用层增加预校验,或在数据库中调整约束条件(如扩展 CHECK 的范围)。

重要提示:应用层的校验不能替代数据库约束。应用层校验可以提升用户体验(快速反馈),但数据库约束是数据一致性的最后一道防线。两者应配合使用,而非二选一。

通过合理使用 PRIMARY KEY、FOREIGN KEY、UNIQUE、NOT NULL、CHECK 和 DEFAULT,你可以构建出一个健壮、自解释且难以被破坏的数据库结构。在面对报错时,理解约束的本质能帮助你更快地从数据层面找到根源。

参考资料

  • PostgreSQL constraints
  • MySQL CREATE TABLE constraints
  • SQL Server constraints
  • SQLite CREATE TABLE constraints
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
数据库 MySQL SQL postgresql
相关文章 更多
SQL增删改操作规范:INSERT、UPDATE与DELETE语句详解
SQL增删改操作规范:INSERT、UPDATE与DELETE语句详解

掌握SQL增删改核心规范:INSERT必须指定列清单以防结构变更错误;UPDATE和DELETE执行前务必通过SELECT确认WHERE条件范围;利用事务BEGIN/ROLLBACK机制实现误操作回滚。本文结合PostgreSQL语法与跨库差异,提供从语句编写到结果验证的完整安全操作流程,帮助开发者规避生产环境数据风险。

解决SQL插入数据违反约束的报错
解决SQL插入数据违反约束的报错

后端开发中遇到INSERT语句因约束失败报错怎么办?本文详解如何解读NOT NULL、UNIQUE、CHECK及FOREIGN KEY错误信息,通过查看表结构和对比输入参数快速定位原因,并提供修正数据、调整插入顺序及幂等处理的具体方案,帮助开发者高效解决数据库写入异常。

用集合操作或临时表替代SQL游标的方法与案例
用集合操作或临时表替代SQL游标的方法与案例

开发者常因游标逐行处理导致SQL执行缓慢。本文详解如何使用集合操作(UPDATE FROM)、临时表批量JOIN以及按主键范围分批处理来替代游标。涵盖NULL值处理、索引优化及事务一致性检查,提供可落地的代码案例与验证方法。

SQL游标常见错误排查:死锁与资源未释放问题
SQL游标常见错误排查:死锁与资源未释放问题

深入解析SQL游标导致的死锁与资源未释放问题。通过PostgreSQL与MySQL语法对比,展示如何识别长事务持锁、分析锁等待链,并提供短事务提交、异常清理及批量处理的最佳实践,确保数据库连接与锁资源及时释放。

为什么SQL开发应尽量避免使用游标:性能瓶颈分析
为什么SQL开发应尽量避免使用游标:性能瓶颈分析

深入分析SQL游标在逐行FETCH时的性能瓶颈,包括往返开销、锁竞争及连接资源占用。提供将游标逻辑改写为集合操作(UPDATE/INSERT SELECT)的实战方法,以及必须逐行处理时的分批提交策略。通过EXPLAIN和锁监控验证优化效果,适用于评估数据库交互方案的后端开发者。

SQL中怎么创建和删除约束
SQL中怎么创建和删除约束

后端开发者在维护数据库时,常需对现有表添加主键、唯一或外键约束。若直接执行ADD CONSTRAINT,往往因存量数据不合规导致报错。本文详解操作前的数据清洗步骤、标准SQL语法及MySQL等特殊写法,帮助你在生产环境安全完成结构变更。

SQL分组统计查询:GROUP BY与HAVING子句用法示例
SQL分组统计查询:GROUP BY与HAVING子句用法示例

针对 SQL 初学者的分组统计实战指南。深入解析 GROUP BY 分组机制、WHERE 与 HAVING 的执行时机差异,以及 COUNT 函数对 NULL 值的处理逻辑。通过具体代码示例演示如何正确筛选聚合结果,并排查因 JOIN 连接导致的统计数据异常,提升报表准确性。

SQL Server与MySQL游标基本语法及完整代码示例
SQL Server与MySQL游标基本语法及完整代码示例

本文详细对比SQL Server和MySQL中游标的基本用法。从DECLARE声明到FETCH遍历,再到CLOSE关闭与DEALLOCATE/Handler清理,解析两者在语法结构、变量接收及异常处理上的核心差异。通过标准代码示例展示如何安全使用游标,避免资源泄漏,适用于需要进行数据库存储过程开发或跨平台迁移的开发者。

SQL游标是什么:工作原理与适用场景详解
SQL游标是什么:工作原理与适用场景详解

深入解析SQL游标的工作机制,包括DECLARE、OPEN、FETCH、CLOSE完整生命周期。通过代码示例说明何时使用游标处理逐行逻辑,对比集合操作的优劣,强调资源释放的重要性,为开发者提供清晰的适用边界判断标准。

SQL多表连接区别:INNER JOIN与LEFT JOIN的使用场景
SQL多表连接区别:INNER JOIN与LEFT JOIN的使用场景

深入解析SQL中INNER JOIN与LEFT JOIN的核心区别。通过users和orders表实例,展示匹配行保留与NULL补位机制,重点讲解ON与WHERE子句中放置右表过滤条件的不同后果,提供防止LEFT JOIN退化的实战技巧及行数异常排查步骤。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
AirBuddy 3 macOS版
AirBuddy 3 macOS版
macOS

AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

AirServer macOS版
AirServer macOS版
macOS

AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

AnyDesk macOS版
AnyDesk macOS版
macOS

AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

WINDOWS 更多
讯飞绘文 网页版
讯飞绘文 网页版
Windows

讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

AirServer Windows版
AirServer Windows版
Windows

AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

AlwaysUp Windows版
AlwaysUp Windows版
Windows

AlwaysUp是一款面向Windows的系统服务注册与程序托管工具,可让普通应用、脚本及批处理在无人登录时随系统启动,并通过状态检测、异常重启、资源监控和邮件通知保障关键任务持续运行。

即将离开本站
您即将前往第三方网站,请确认是否继续?