MySQL:约束(Constraints)

在数据库设计中,约束(Constraints)扮演着至关重要的角色,它们确保了数据库中数据的完整性和有效性。

MySQL作为广泛使用的开源关系型数据库管理系统,自然也支持多种类型的约束。在 MySQL 中,约束是指对表中数据的一种约束,能够帮助数据库管理员更好地管理数据库,并且能够确保数据库中数据的正确性和有效性。

在 MySQL 中可以使用 SHOW CREATE TABLE 语句来查看表中的约束。

MySQL 约束类别

约束是表级的强制规定,用于保证表中数据的完整性和有效性。完整性包括精确性和可靠性。MySQL中的约束可以分为以下几类:

  1. 非空约束(NOT NULL):确保字段值不为NULL。
  2. 唯一性约束(UNIQUE):确保字段或字段组合中的值唯一。
  3. 主键约束(PRIMARY KEY):唯一标识表中的每一行,相当于唯一性约束+非空约束的组合。
  4. 外键约束(FOREIGN KEY):用于维护两个表之间的关系,确保参照完整性。
  5. 检查约束(CHECK,适用于某些数据库版本和类型,如Oracle):确保字段值满足特定条件。
  6. 默认值约束(DEFAULT):当插入记录时,如果字段没有指定值,则使用默认值。

以上 6 种约束中,一个数据表中只能有一个主键约束,其它约束可有多个。

主键约束

主键约束使用最频繁的约束。在设计数据表时,一般情况下,都会要求表中设置一个主键。

主键是表的一个特殊字段,该字段能唯一标识该表中的每条信息。例如,学生信息表中的学号是唯一的。

主键(PRIMARY KEY)的完整称呼是"主键约束"

使用主键应注意以下几点:

  • 每个表只能定义一个主键。一个字段名只能在联合主键字段表中出现一次。

  • 唯一性原则 :主键值必须唯一标识表中的每一行,且不能为 NULL,即表中不可能存在有相同主键值的两行数据。

  • 最小化原则:联合主键不能包含不必要的多余字段。当把联合主键的某一字段删除后,如果剩下的字段构成的主键仍然满足唯一性原则,那么这个联合主键是不正 确的。

设置主键 PRIMARY KEY

创建表时设置主键

在创建数据表时设置主键约束,既可以为表中的一个字段设置主键,也可以为表中多个字段设置联合主键。

单字段主键

CREATE TABLE 语句中,通过 PRIMARY KEY 关键字来指定主键。

在定义字段的同时指定主键,语法格式如下:

sql 复制代码
<字段名> <数据类型> PRIMARY KEY [默认值]

CREATE TABLE student(
	id INT(4) PRIMARY KEY AUTO_INCREMENT,
);

也可以在定义完所有字段之后指定主键,语法格式如下:

sql 复制代码
[CONSTRAINT <约束名>] PRIMARY KEY [字段名]

CREATE TABLE student(
	id INT(4),
	PRIMARY KEY(id)
);
联合主键

所谓的联合主键 ,就是这个主键是由一张表中多个字段组成的。

例如:设计学生选课表,要限定的是一个学生只能选择同一课程一次。因此,学生编号和课程编号可以放在一起共同作为主键,这也就是联合主键了。

主键由多个字段联合组成,语法格式如下:

sql 复制代码
PRIMARY KEY [字段1,字段2,...,字段n]

CREATE TABLE student(
	id INT(4),
	courseID INT(4),
	class VARCHAR(10),
	PRIMARY KEY(id,courseID)
);

当主键是由多个字段组成时,不能直接在字段名后面声明主键约束

修改表时添加主键 ADD PRIMARY KEY

在修改数据表时添加主键约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名> ADD PRIMARY KEY(<字段名>);

ALTER TABLE student ADD PRIMARY KEY(id);

通常情况下,当在修改表时要设置表中某个字段的主键约束时,要确保设置成主键约束的字段中值不能够有重复 的,并且要保证是非空的。否则,无法设置主键约束。

删除主键 DROP PRIMARY KEY

删除主键约束的语法格式如下所示:

sql 复制代码
ALTER TABLE <数据表名> DROP PRIMARY KEY;

ALTER TABLE student DROP PRIMARY KEY;

由于主键约束在一个表中只能有一个,因此不需要指定主键名就可以删除一个表中的主键约束。

AUTO_INCREMENT

通过给字段添加 AUTO_INCREMENT 属性来实现主键自增长。语法格式如下:

sql 复制代码
字段名 数据类型 AUTO_INCREMENT
  • 默认情况下,AUTO_INCREMENT 的初始值是 1,每新增一条记录,字段值自动加 1

  • 一个表中只能有一个字段使用 AUTO_INCREMENT 约束,且该字段必须有唯一索引,以避免序号重复(即为主键或主键的一部分)。

  • AUTO_INCREMENT 约束的字段必须具备 NOT NULL 属性

  • AUTO_INCREMENT 约束的字段只能是整数类型(TINYINT、SMALLINT、INT、BIGINT 等)。

  • AUTO_INCREMENT 约束字段的最大值受该字段的数据类型约束,如果达到上限 ,AUTO_INCREMENT 就会失效

  • 通常情况下 AUTO_INCREMENT 都作为id字段的约束条件,并作为主键

指定自增字段初始值

如果第一条记录设置了该字段的初始值,那么新增加的记录就从这个初始值开始自增。

sql 复制代码
CREATE TABLE student(
	id INT NOT NULL AUTO_INCREMENT,
	PRIMARY KEY(id)
)AUTO_INCREMENT=99;  #主键从99开始递增

若手动添加一个主键中已存在的值,报 Duplicate key error(唯一键冲突)。在这之后,再插入新的数据时,自增 id 就是 3,这样就出现了自增字段值不连续的情况。

外键约束

外键约束 (FOREIGN KEY) 是表的一个特殊字段,经常与主键约束一起使用。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表)外键所在的表就是从表(子表) 。用来确保数据的一致性,有助于维护数据的完整性

主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。

一个表可以有一个或多个外键,外键可以为空值 ,若不为空值,则每一个外键的值必须等于主表中主键的某个值

假设有两个表,一个是商品表(products),另一个是订单表(orders)。

每个订单可以包含多个商品。为了建立商品与订单之间的关系,可以在订单表中添加一个外键列来引用商品表的主键。

定义规则

定义外键时,需要遵守下列规则:

  • 主表必须已经存在于数据库中,或者是当前正在创建的表,且必须为主表定义主键。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表 ,这种结构称为自参照完整性

  • 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。

  • 在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。

  • 外键中列的数目必须和主表的主键中列的数目相同

  • 外键中列的数据类型必须和主表主键中对应列的数据类型相同 。如果不满足这样的要求,在创建从表时,就会出现

    `'ERROR 1005(HY000): Can't create table'错误。

设置外键 FOREIGN KEY

创建表时设置外键约束

CREATE TABLE 语句中,通过 FOREIGN KEY 关键字来指定外键,具体的语法格式如下:

sql 复制代码
[CONSTRAINT <外键名>] FOREIGN KEY 字段名 [,字段名2,...]  
REFERENCES <主表名> 主键列1 [,主键列2,...]
sql 复制代码
CREATE TABLE student (
	id INT PRIMARY KEY NOT NULL,
	name VARCHAR(6),
	deptID INT(10),
	CONSTRAINT fk_school_student
	FOREIGN KEY (deptID) REFERENCES school (id) 
);
'''
在表student添加了名为fk_school_student的外键约束,外键名称为deptID,依赖于表school的主键id
'''
修改表时添加外键约束

添加外键约束的前提是:从表中外键列中的数据必须与主表中主键列中的数据一致或者是没有数据

在修改数据表时添加外键约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名> ADD CONSTRAINT <外键名>  
FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
sql 复制代码
ALTER TABLE student 
ADD CONSTRAINT fk_school_student
FOREIGN KEY (deptID) REFERENCES school (id);

在为已经创建好的数据表添加外键约束时,要确保添加外键约束的列的值全部来源于主键列,并且外键列不能为空

删除外键约束 DROP FOREIGN KEY

键一旦删除,就会解除主表和从表间的关联关系。

删除外键约束的语法格式如下所示:

sql 复制代码
ALTER TABLE <表名> DROP FOREIGN KEY <外键约束名>;

ALTER TABLE student DROP FOREIGN KEY fk_school_student

唯一约束

唯一约束(Unique Key)是指所有记录中字段的值不能重复出现

例如,为 id 字段加上唯一性约束后,每条记录的 id 值都是唯一的,不能出现重复的情况。如果其中一条记录的 id 值为'0001',那么该表中就不能出现另一条记录的 id 值也为'0001'。

唯一约束与主键约束相似的是它们都可以确保列的唯一性。不同的是,唯一约束在一个表中可有多个 ,并且设置唯一约束的列允许有空值但是只能有一个空值

主键约束在一个表中只能有一个,且不允许有空值。比如,在用户信息表中,为了避免表中用户名重名,可以把用户名设置为唯一约束。

设置唯一约束 UNIQUE

创建表时设置唯一约束

唯一约束可以在创建表时直接设置,通常设置在除了主键以外的其它列上。

在定义完列之后直接使用 UNIQUE 关键字指定唯一约束,语法格式如下:

sql 复制代码
<字段名> <数据类型> UNIQUE

CREATE TABLE student(
	id INT PRIMARY KEY,
	name VARCHAR(6) UNIQUE,
	location VARCHAR(10)
);
修改表时设置唯一约束

在修改表时添加唯一约束的语法格式为:

sql 复制代码
ALTER TABLE <数据表名> ADD CONSTRAINT <唯一约束名> UNIQUE(<列名>);

ALTER TABLE student 
ADD CONSTRAINT unique_name UNIQUE name;

删除唯一约束 DROP INDEX

在 MySQL 中删除唯一约束的语法格式如下:

sql 复制代码
ALTER TABLE <表名> DROP INDEX <唯一约束名>;

ALTER TABLE student DROP INDEX unique_name;

检查约束

检查约束(CHECK),定义了在表中的列上允许的值的条件,是用来检查数据表中字段值有效性的一种手段。

例如,学生信息表中的年龄字段是没有负数的,并且数值也是有限制的。如果是大学生,年龄一般应该在 18~30 岁之间。在设置字段的检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入。

设置检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入。

默认值约束非空约束 也可以看作是特殊的检查约束。

检查约束可能会对插入和更新的性能产生一定的影响,因为在每次操作时都需要对约束条件进行检查。因此,在设计表结构和应用检查约束时,需要谨慎考虑性能方面的影响。

选取检查约束的字段

检查约束使用 CHECK 关键字,具体的语法格式如下:

sql 复制代码
CHECK <表达式>

其中,"表达式"指的就是 SQL 表达式,用于指定需要检查的限定条件

若将 CHECK 约束子句置于表中某个列的定义之后,则这种约束也称为基于列的 CHECK 约束

在更新表数据的时候,系统会检查更新后的数据行是否满足 CHECK 约束中的限定条件。MySQL 可以使用简单的表达式来实现 CHECK 约束,也允许使用复杂的表达式作为限定条件,例如在限定条件中加入[[Subqueries 子查询|子查询]]。

若将 CHECK 约束子句置于所有列的定义以及主键约束和外键定义之后,则这种约束也称为基于表的 CHECK 约束 。该约束可以同时对表中多个列设置限定条件

设置检查约束 CHECK

创建表时

创建表时设置检查约束的语法格式如下:

sql 复制代码
CHECK(<检查约束>)

CREATE TABLE student(
	id INT(4) PRIMARY KEY NOT NULL,
	name VARCHAR(2) UNIQUE,
	age INT(2),
	CHECK (age>18 AND age<28)
)
# 插入或更新的行必须满足年龄大于18且小于28的条件,否则操作将被拒绝
修改表时

修改表时设置检查约束的语法格式如下:

sql 复制代码
ALTER TABLE <表名> ADD CONSTRAINT <检查约束名> CHECK(<检查约束>)

ALTER TABLE student 
ADD CONSTRAINT check_age CHECK (age>18 AND age<28);

删除检查约束 DROP CONSTRAINT

修改表时删除检查约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名> DROP CONSTRAINT <检查约束名>;

ALTER TABLE student DROP CONSTRAINT check_age;

非空约束

非空约束(NOT NULL)指字段的值不能为空。对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错。

设置非空约束 NOT NULL

创建表时

创建表时可以使用 NOT NULL 关键字设置非空约束,具体的语法格式如下:

sql 复制代码
<字段名> <数据类型> NOT NULL;
修改表时

修改表时设置非空约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名>  
CHANGE COLUMN <字段名>  
<字段名> <数据类型> NOT NULL;

ALTER TABLE student
CHANGE COLUMN id
id INT NOT NULL;

删除非空约束 CHANGE COLUMN NULL

修改表时删除非空约束的语法规则如下:

sql 复制代码
ALTER TABLE <数据表名>  
CHANGE COLUMN <字段名> <字段名> <数据类型> NULL;

ALTER TABLE student
CHANGE COLUMN id id INT NULL;

默认值约束

默认值(Default) 的完整称呼是默认值约束(Default Constraint)

用来指定某列的默认值。在表中插入一条新记录时,如果没有为某个字段赋值,系统就会自动为这个字段插入默认值。

例如,在注册学生信息时,如果不输入学生的性别,那么会默认设置一个性别或者输入一个"未知"。

默认值约束通常用在已经设置了[[#非空约束]]的列,这样能够防止数据表在录入数据时出现错误。

设置默认值约束 DEFAULT

创建表时设置

创建表时可以使用 DEFAULT 关键字设置默认值约束,具体的语法格式如下:

sql 复制代码
<字段名> <数据类型> DEFAULT <默认值>;

'''<默认值>为该字段设置的默认值,如果是字符类型,要用单引号括起来。'''

在创建表时为列添加默认值,可以一次为多个列添加默认值,需要注意不同列的数据类型

sql 复制代码
CREATE TABLE student (
	id INT PRIMARY KEY,
	class VARCHAR(10) DEFAULT '2022-01',
	courses INT DEFAULT 0
)
修改表时设置 CHANGE COLUMN DEFAULT

修改表时添加默认值约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名>  
CHANGE COLUMN <字段名> <数据类型> DEFAULT <默认值>;

ALTER TABLE student 
CHANGE COLUMN course INT DEFAULT 1;

删除默认值约束 CHANGE COLUMN DEFAULT NULL

修改表时删除默认值约束的语法格式如下:

sql 复制代码
ALTER TABLE <数据表名>  
CHANGE COLUMN <字段名> <字段名> <数据类型> DEFAULT NULL;

ALTER TABLE student
CHANGE COLUMN courses 
courses INT DEFAULT NULL;

非空约束和默认约束

大多数关系型数据库中,同一个字段的非空约束和默认约束不能同时存在。原因是这两种约束的定义冲突了。

非空约束是要求该字段的值不能为空,而默认约束则是给字段一个默认值。如果同时定义了这两种约束,那么当插入数据时,就出现了冲突:默认约束为该字段设置了默认值,但是非空约束又要求该字段的值不能为空,这两种约束的要求相互冲突,导致无法满足同时存在。

例如,考虑以下SQL语句:

sql 复制代码
CREATE TABLE mytable (
   id INT PRIMARY KEY,
   name VARCHAR(50) NOT NULL,
   age INT NOT NULL DEFAULT 18
);

这个表定义了三个字段:id、name和age。其中,name字段定义为非空,age字段定义为默认值为18。这样定义时会引起报错,因为非空约束与默认约束定义冲突了。

  1. 非空约束:非空约束要求该字段的值不能为空。这意味着在插入或更新数据时,必须显式地为该字段提供一个非空的值。如果未提供值或提供了空值,将触发非空约束的违规错误。

  2. 默认约束:默认约束为字段提供了一个默认值。当插入数据时,如果没有显式地为该字段提供值,数据库将使用默认值作为该字段的值。

解决这个冲突的方法是要么去掉默认约束,要么去掉非空约束,确保约束的定义不会相互冲突。

需要注意的是,不同的数据库管理系统对于这种规则的支持程度可能不一样,因此具体实现可能存在一些不同,但是一般来说,同一个字段的非空约束与默认约束不能同时存在。

例如,在学生信息表中,如果不添加学生姓名,那么这条记录是没有用的。

总结

MySQL中的约束是保证数据完整性和可靠性的重要工具。通过合理使用这些约束,可以确保数据库中存储的数据既准确又有效。在设计数据库表时,应根据实际需求选择适当的约束,以确保数据的完整性和准确性。

相关推荐
Asthenia041231 分钟前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom1 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide1 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9651 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04122 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫