0

0

SQL 如何校验数据完整性?

冰川箭仙

冰川箭仙

发布时间:2026-01-25 18:53:11

|

218人浏览过

|

来源于php中文网

原创

CHECK约束用于字段级业务规则校验,如年龄≥0、邮箱含@;外键保障引用完整性,需注意ON DELETE行为与索引要求;UNIQUE+NOT NULL可替代弱主键;应用层与数据库约束须并存,不可互相替代。

sql 如何校验数据完整性?

用 CHECK 约束定义字段级业务规则

CHECK 约束是最直接的数据完整性控制手段,它在插入或更新时强制校验表达式是否为 TRUE。比如确保年龄不为负数、邮箱必须含 @ 符号,这类逻辑适合用 CHECK 实现。

注意 PostgreSQL 和 SQL Server 支持函数(如 POSITIONLEN)参与 CHECK 表达式,但 MySQL 5.7 及更早版本只允许确定性函数,UUID()NOW() 会报错;MySQL 8.0+ 已放宽限制,但仍需避免子查询和用户变量。

  • 写法示例:ALTER TABLE users ADD CONSTRAINT chk_age CHECK (age >= 0 AND age
  • 复合条件建议拆成多个 CHECK,便于定位失败原因(单个 CHECK 失败只报“check constraint violated”,不指明哪部分错)
  • NULL 值默认通过 CHECK(因为 NULL > 0 结果是 UNKNOWN,不是 FALSE),若要禁止 NULL,得额外加 NOT NULL

外键约束(FOREIGN KEY)防止孤立记录

外键是保障引用完整性的核心机制,它确保子表中某列的值必须存在于父表主键/唯一键中。一旦忽略,就会出现“订单有 customer_id=999,但 customers 表里根本没有这条记录”的情况。

常见陷阱是建表时没指定 ON DELETE 行为:默认是 RESTRICT,删父记录时若子表有关联数据就报错 ERROR 1451 (HY000): Cannot delete or update a parent row;想级联删除得显式写 ON DELETE CASCADE,但务必确认业务是否允许——误删客户导致所有订单消失,就是典型副作用。

  • 添加外键前,先确保父表被引用列有索引(否则 MySQL 会静默创建,PostgreSQL 则直接报错 there is no unique constraint matching given keys
  • SQL Server 中临时禁用外键用 ALTER TABLE orders NOCHECK CONSTRAINT fk_customer_id,但之后必须手动验证数据一致性,不能依赖它长期绕过检查
  • 跨 schema 引用需写全名,如 REFERENCES sales.customers(id),否则可能意外绑定到当前 schema 下同名表

用 UNIQUE + NOT NULL 替代弱主键

有些表没有自然主键(比如日志表、中间表),但又需要防止重复行或空值干扰统计,这时 UNIQUE 配合 NOT NULL 是比自增 ID 更贴近语义的选择。

Beautiful.ai
Beautiful.ai

AI在线创建幻灯片

下载

例如订单明细表中,(order_id, product_id) 联合唯一能防止同一订单重复添加同一商品;若只对 product_id 加 UNIQUE,则无法阻止不同订单里出现相同商品——关键看业务上“重复”是如何定义的。

  • UNIQUE 索引允许一个 NULL(标准 SQL 行为),MySQL InnoDB 把 NULL 当作独立值处理,而 PostgreSQL 认为所有 NULL 彼此相等,所以后者在 UNIQUE (col) 下只能存一个 NULL
  • 联合唯一约束的列顺序影响查询效率:如果常按 WHERE order_id = ? AND product_id = ? 查询,就把 order_id 放前面
  • 某些 ORM(如 Django)生成迁移时默认给外键加 db_constraint=True,但若数据库已存在脏数据,迁移会失败,得先清理再执行

应用层校验和数据库约束必须同时存在

只靠数据库约束不够安全——网络中断、事务未提交、批量导入跳过约束(如 MySQL 的 LOAD DATA INFILE 默认忽略 CHECK)、或者应用直连数据库绕过 ORM 层,都可能让坏数据漏进来。

反过来,只做应用层校验也不可靠:多个服务共用同一库、DBA 手动修复数据、甚至同事写了个脚本清库存,这些场景下数据库自己得守住底线。

  • 应用层用正则校验邮箱格式(如 /^.+@.+\..+$/),数据库用 CHECK 确保非空且含 @(email IS NOT NULL AND email LIKE '%@%'),两者覆盖范围不同,不能互相替代
  • 高并发下应用层的“先查后插”(check-then-act)必然产生竞态,必须靠数据库的 INSERT ... ON CONFLICT DO NOTHING(PostgreSQL)或 INSERT IGNORE(MySQL)兜底
  • 定期用 SELECT COUNT(*) FROM table WHERE NOT (condition) 检查约束是否被历史数据绕过,尤其是上线新 CHECK 后没做 backfill 的字段
约束不是设完就一劳永逸的事。真正难的是理解每条约束背后的业务含义,以及当它被触发时,系统该拒绝、修正,还是告警——这往往取决于上下文,而不是 SQL 语法本身。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

686

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

325

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1159

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

359

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

758

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

577

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

420

2024.04.29

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

58

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.9万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 810人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号