MySQL:表的约束

文章目录


SQL 中,表的约束是用于限制表中数据的规则,目的是保证数据的完整性、一致性和有效性。通过约束,可以防止不合理或错误的数据进入表中,确保数据库中数据的质量,约束特性在SQL中一般在创建的时候定义,或者后续使用ADD添加


一,非空

指定一个字段,每次添加数据时,这个字段的数据都不能为空,否则报错,使用关键字NOT NULL

演示代码

sql 复制代码
CREATE TABLE student(
	id INT,
	name varchar(50) NOT NULL
);

标识name字段不能为空,我们想表中插入一个name为空的数据

sql 复制代码
INSERT INTO student (id,name) VALUES(2,NULL);
SELECT * FROM student;

演示结果

提示这里的name的值不能为空


二,唯一

指定一个字段,使表中的这个字段里面的数据都不相同,使用关键字为UNIQUE

sql 复制代码
CREATE TABLE grade(
  id int UNIQUE,
  point int
);

演示代码

sql 复制代码
INSERT INTO grade(id,point) VALUES(1,85);
INSERT INTO grade(id,point) VALUES(1,90);

演示结果

提示这个1作为key输入了两次,报了错误


三,主键约束

主要是使用PRIMARY KEY,一般用于标记一个表中的唯一标识符数据

sql 复制代码
CREATE TABLE students(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50)
)

唯一标识表中的每条记录,确保记录不重复,且不为空,一个表只能有一个主键,主键字段的值必须唯一且非空,每次我们想插入一个数据,都会校验一下插入行的PRIMARY_KEY标记的数据,数据的要求是再表中不能有重复的,并且不能为空同时拥有UNIQUENOT NULL两个特性。

在实际项目当中用于数据库当中作为数据行的唯一标识符,一般在业务代码中和AUTO INCREASE一起使用,这样我们插入数据直接需要的数据就可以。但是这里有个前提,就是表中的主键字段的个数只能有一个

sql 复制代码
INSERT INTO students(name) VALUES('小红'),('小刚');
SELECT * FROM students;

演示结果


四,默认值

当我们插入数据时,没有指定数据,那么数据表就会采用我们在创建表的时候设置的默认值,主要使用的关键字是DEFAULT

使用格式

sql 复制代码
CREATE TABLE NUMBERS(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) DEFAULT '学生'
);

演示代码

sql 复制代码
INSERT INTO numbers VALUES(),();

演示结果

我们没有插入name数据,这里数据表直接采用默认值


五,FOREIGN KEY

简单来讲,FOREIGN KEY(外键)就是用来连接两个数据表的"桥梁",让它们通过共享的ID进行映射和引用。

想象一下,一本书的目录和正文:目录里列出章节号(ID),对应正文的实际内容。只有通过这个"对应关系",我们才能快速翻到想看的部分,让整本书变得井井有条、好用简便。外键就是数据库里的"目录机制"------它确保子表(比如订单表)里的引用ID,总能准确指向父表(比如用户表)里的真实记录,避免数据"孤儿"或混乱。

再举个学校学生的例子:一个学生的完整信息,包括基本资料(姓名、ID)、家庭背景、成绩单、个人经历和奖项。如果把所有这些都塞进一张大表,会不会乱成一锅粥?数据冗余、查询慢,还难维护。

这就是为什么我们用关系型数据库设计:将相似的数据分类存入不同表,再通过外键建立连接。

父表:学生基本表(id PRIMARY KEY, name)。
子表:成绩表(student_id FOREIGN KEY REFERENCES 学生表(id), score)。
其他子表:家庭表(student_id FOREIGN KEY...)、奖项表(student_id FOREIGN KEY...)。

这样,学生信息就"模块化"了!查询时超级方便:只需拿到学生的ID,就能轻松"跳"到相关表拉数据。比如,用SQLJOIN查询,就能一键拼出"学生A的成绩+家庭背景"------高效又不乱。

总之,外键不是魔法,但它是数据库"防乱神器",帮你从杂乱数据中构建清晰的"整体画像"。

演示代码:创建两个表,分别是成绩表和学生表,需要注意的是外键对应的值必须要有唯一性,比如PRIMARY KEYUNIQUE

sql 复制代码
CREATE TABLE student(
  id int PRIMARY KEY,
  name VARCHAR(50)
);

CREATE TABLE grades(
  id int PRIMARY KEY AUTO_INCREMENT,
  math int,
  english int,
  user_id int,
  FOREIGN KEY(user_id) REFERENCES student(id) ON DELETE CASCADE
) 

这里我们多加了一个ON DELETE CASCADE,逻辑意义就是当删除grades中对应的student的数据时,外键对应的数据grades的数据也会被删除.

我们来在student中插入几个数据行

sql 复制代码
INSERT INTO student (id,name) VALUES (1'小甘'),(2,'小红'),(3,'小刚'),(4,'小新'),(5,'小锦');

演示结果:有五行数据

我们再在grades中添加数据

sql 复制代码
INSERT INTO grades (id,math,english,user_id) 
VALUES (2,90,80,2),(3,70,50,3),(4,68,85,4),(5,95,75,5);

演示结果

不过这里我们需要注意的是,如果我们的user_id的值选择studentid之外的值,那么就会报错

演示代码

sql 复制代码
INSERT INTO grades (id,math,english,user_id) 
VALUES (6,90,80,6);

演示结果

因为外键没有找到需要对应的值,所以发生了一个报错

删除问题

想象一下,在电商网站上,你下了一个单(订单记录),但后来你注销了账号(用户被删)。这个订单该怎么办?跟着一起消失,还是留下来"孤零零"?这就是主表(用户表)和从表(订单表)的删除关系------订单里的user_id外键引用用户的主键,确保"订单不离用户"。

ON DELETE CASCADE关键字创建外键,就能提供保障:删除用户(主表)时,系统自动把所有相关订单(从表)一并删除。简单高效,避免手动追删。

如果不用CASCADE,会怎样:默认情况下(不指定ON DELETE),MySQLRESTRICT规则:尝试删用户时,如果订单还引用它,会抛异常Cannot delete or update a parent row: a foreign key constraint fails。这阻止了删除,保护数据完整性------防止"孤儿订单":用户没了,但订单还挂着无效的user_id,查询时我们不知道订单属于谁,数据就乱套了。

业务上,怎么破?有三种常见策略:

先删从表,再删主表:手动清订单,然后删用户(适合审计需求)。

一起删:用CASCADE,一键搞定(你的电商场景首选)。

都不删,或软删:用ON DELETE SET NULLuser_id设空(订单匿名保留),或干脆不删用户,只标记"注销"。

这样,数据库像个严谨的"仓库管理员"------不会让货单"认错爹"!

演示代码:这里我们删除一个主表的数据试试哦

sql 复制代码
DELETE FROM student WHERE id = 1;

演示结果

student:

grades:

这里我们删除了一个student的数据,它对应的grades的数据也被一并删除了


六,CHECK

CHECK是一个约束条件哦,就像我们在参加招聘会一样,面试官要求学历不低于本科,年龄不低于20岁,不高于35岁,否则不允许投递简历(数据),但是CHECK这个表约束特性只在MySQL8.0版本才存在

我们来演示一下:为表添加约束条件,然后添加数据

sql 复制代码
ALTER TABLE student ADD CONSTRAINT age CHECK(age<35);
INSERT INTO student (id,name ,age) VALUES(7,'小平',80);

演示结果

这里添加限制条件需要记住,使用CONSTRAINT关键字,因为age大于35,所以CHECK不允许此数据添加通过

相关推荐
Li zlun4 小时前
MySQL 性能监控与安全管理完全指南
数据库·mysql·安全
养生技术人5 小时前
Oracle OCP认证考试题目详解082系列第48题
运维·数据库·sql·oracle·database·开闭原则·ocp
海阳宜家电脑5 小时前
Lazarus使用TSQLQuery更新的一点技巧
数据库·lazarus·tsqlquery
丨我是张先生丨6 小时前
SQLSERVER 查找存储过程中某个变量
数据库
感谢地心引力6 小时前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
韩立学长7 小时前
【开题答辩实录分享】以《走失人口系统档案的设计与实现》为例进行答辩实录分享
mysql·mybatis·springboot
lypzcgf7 小时前
Coze源码分析-资源库-编辑数据库-后端源码-数据存储层
数据库·coze·coze源码分析·智能体平台·ai应用平台
jackaroo20207 小时前
后端_Redis 分布式锁实现指南
数据库·redis·分布式
liuy96158 小时前
迷你论坛项目
数据库