1. 约束(constraint) 概述

1.1 为什么需要约束

数据完整性(Data Integrity) 是指数据的精准性(Accuracy) 和 可靠性(Reliability)。防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的

为了保证数据的完整性,SQL 规范以约束的方式对表数据进行额外的条件限制 。从以下四个方面考虑:

  • 实体完整性(Entity Integrity) :例如:在同一张表中,不能存在两条完全相同无法区分的记录
  • 域完整性(Domain Integrity):例如:年龄范围 0 - 120 ,性别范围 “男/女”
  • 引用完整性(Referential Int):例如:员工所在部门,在部门表中要有这个部门编号
  • 用户自定义完整性(User-defined Intergrity):例如:用户名唯一、密码不能为空等

1.2 什么是约束

约束是表级的强制要求

可以在创建表时添加约束,或在修改表时添加/删除约束

1.3 约束的分类

  • 根据约束数据列的限制,约束可分为:
    • 单列约束:每个约束只约束一列
    • 多列约束:每个约束可以约束多列
  • 根据约束的作用范围
    • 列级约束:只作用在一个列上,定义在列后面
    • 表级约束:可以作用在多个列上,单独定义一行
约束 位置 支持的约束类型 是否可以起约束名
列级约束 列的后面 语法都支持,但是外键没有效果 不可以
表级约束 所有列的下面 默认和非空不支持,其他支持 可以(主键没有效果)
  • 根据约束的作用
    • NOT NULL 非空约束
    • UNIQUE 唯一约束
    • PRIMARY KEY 主键(非空且唯一)约束
    • FOREIGN KEY 外键约束
    • CHECK 检查约束
    • DEFAULT 默认值约束

MySQL 不支持 check 约束,但是可以使用,并没有任何效果

  • 查看某个表的已有约束
information_schema 数据库名(系统库)
table_constraints 表名称(专门存储各个表的约束)
SELECT *
FROM information_schema.TABLE_CONSTRAINTS
WHERE table_name = '表名'

2.非空约束

2.1 作用

限制某个字段的值不可为空

2.2 关键字

NOT NULL

2.3 特点

  • 默认,所有类型的值都可以是 NULL
  • 非空约束只能是列级约束,并且不可组合非空
  • 一个表可以给多个字段添加非空约束
  • 空字符串 ‘’ 不等于 NULL,0 也不等于 NULL

2.4 添加非空约束

  1. 创建表时
CREATE TABLE 表名称(
	字段名 数据类型,
	字段名 数据类型 NOT NULL,
	字段名 数据类型 NOT NULL
);
  1. 修改表时
alter table 表名称 
modify 字段名 数据类型 NOT NULL;

举例:


创建表时添加约束

CREATE TABLE test1(
id INT NOT NULL,
last_name VARCHAR(15) NOT NULL,
email VARCHAR(25),
salary DECIMAL(10,2)
);

DESC test1;

INSERT INTO test1(id,last_name,email,salary)
VALUES(1,'Tom','tom@126.com',3400);

> 1048 - Column 'last_name' cannot be null
INSERT INTO test1(id,last_name,email,salary)
VALUES(2,NULL,'tom@126.com',3400);

> 1048 - Column 'id' cannot be null
INSERT INTO test1(id,last_name,email,salary)
VALUES(NULL,'Jerry','tom@126.com',3400);

#> 1364 - Field 'last_name' doesn't have a default value
INSERT INTO test1(id,email)
VALUES(2,'abc@126.com');

修改表时添加/删除约束
DESC test1;

添加非空约束
ALTER TABLE test1
MODIFY email VARCHAR(25) NOT NULL;



2.5 删除非空约束

ALTER TABLE test1 MODIFY email VARCHAR(25);

3. 唯一性约束

3.1 作用

限制某个字段的值不可重复(不包括 NULL 值)

3.2 关键字

UNIQUE

3.3 特点

  • 同一个表中可以有多个唯一约束
  • 可以组合唯一 (可以是某个列的值唯一,也可多个列组合的值唯一)
  • 唯一约束允许列值为 NULL
  • 在创建唯一约束时,若不给约束命名,则默认和列名相同
  • MySQL 会给唯一约束的列创建一个唯一索引

3.4 添加唯一约束

  1. 创建表时
CREATE TABLE 表名称(
	字段名 数据类型,
	字段名 数据类型 UNIQUE,
	字段名 数据类型 unique key,
	字段名 数据类型
);

CREATE TABLE 表名称(
	字段名 数据类型,
	字段名 数据类型,
	字段名 数据类型,
	[CONSTRAINT 约束名] unique key(字段名)
);

CREATE TABLE test2(
	id INT UNIQUE, # 列级约束
	last_name VARCHAR(15),
	email VARCHAR(25) UNIQUE,
	salary DECIMAL(10,2),
	
	#表级约束
	CONSTRAINT uk_test2_email UNIQUE(email)
)
  1. 修改表时
字段列表中如果是一个字段,表示该列的值唯一。如果是两个或更多个字段,那么复合唯一,即多个字段的组合是唯一的
方式一:
ALTER TABLE 表名 
ADD CONSTRAINT 约束名 UNIQUE(字段名)
----------------------------------------
ALTER TABLE test2 
ADD CONSTRAINT uk_test2_sal UNIQUE(salary)

方式二:
ALTER TABLE 表名
MODIFY 字段名 字段类型 UNIQUE;
----------------------------------------
ALTER TABLE test2
MODIFY last_name VARCHAR(15) UNIQUE

3.5 复合唯一约束

create table 表名称(
	字段名 数据类型,
	字段名 数据类型,
	字段名 数据类型,
	unique key(字段列表)   
	字段列表中写的是多个字段名,多个字段名用逗号分隔,表示那么是复合唯一,即多个字段的组合是唯一的
);

CREATE TABLE `user`(
id INT,
`name` VARCHAR(15),
`password` VARCHAR(25),
#表级约束
CONSTRAINT uk_user_name_pwd UNIQUE(`name`,`password`)
)

举例:


学生表
create table student(
	sid int, #学号
	sname varchar(20), #姓名
	tel char(11) unique key, #电话
	cardid char(18) unique key #身份证号
);

课程表
create table course(
	cid int, #课程编号
	cname varchar(20) #课程名称
);

选课表
create table student_course(
	id int,
	sid int,
	cid int,
	score int,
	unique key(sid,cid) #复合唯一
);

insert into student values(1,'张三','13710011002','101223199012015623');#成功
insert into student values(2,'李四','13710011003','101223199012015624');#成功
insert into course values(1001,'Java'),(1002,'MySQL');#成功

mysql> select * from student;

+-----+-------+-------------+--------------------+
| sid | sname | tel         | cardid             |
+-----+-------+-------------+--------------------+
| 1   | 张三  | 13710011002 | 101223199012015623 |
| 2   | 李四  | 13710011003 | 101223199012015624 |
+-----+-------+-------------+--------------------+
2 rows in set (0.00 sec)

mysql> select * from course;
+------+-------+
| cid  | cname |
+------+-------+
| 1001 | Java  |
| 1002 | MySQL |
+------+-------+
2 rows in set (0.00 sec)

insert into student_course values
(1, 1, 1001, 89),
(2, 1, 1002, 90),
(3, 2, 1001, 88),
(4, 2, 1002, 56);#成功

mysql> select * from student_course;
+----+------+------+-------+
| id | sid  | cid  | score |
+----+------+------+-------+
| 1  | 1    | 1001 | 89    |
| 2  | 1    | 1002 | 90    |
| 3  | 2    | 1001 | 88    |
| 4  | 2    | 1002 | 56    |
+----+------+------+-------+
4 rows in set (0.00 sec)

insert into student_course values (5, 1, 1001, 88);#失败
#ERROR 1062 (23000): Duplicate entry '1-1001' for key 'sid' 违反sid-cid的复合唯一

3.5 删除唯一约束

  • 添加唯一约束的列上也会自动创建一个唯一索引
  • 删除唯一约束只能通过删除唯一索引的方式删除
  • 删除时需要指定唯一索引的名称,唯一索引的名称与唯一约束的一致
  • 若创建时没有指定名称,若是单列,则默认和列名相同;若是组合列,则默认和括号中第一个列名相同
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名'; 
查看都有哪些约束
ALTER TABLE USER
DROP INDEX uk_name_pwd;

注意:可以通过 show index from 表名称; 查看表的索引

4. PRIMARY KEY 约束

4.1 作用

唯一标识表中的一条记录

4.2 关键字

PRIMARY KEY

4.3 特点

  • 主键约束相当于 非空约束+唯一约束 ,主键约束的列不允许 NULL 值,也不允许有重复值
  • 一个表中最多只可以有一个主键约束,可以建立列级约束也可建立表级约束
  • 主键约束对应着表中的一列或者多列(复合主键)
  • 若是多列组合的复合主键约束,则这些字段值任一都不可为空,且组合值不可重复
  • MySQL 主键名始终是 PRIMARY,自命名无效
  • 当创建主键约束时,系统会自动的在约束列上创建主键索引(目的:根据主键查询,效率更高)。若删除主键约束,则索引自动删除
  • 注意:不可修改主键字段的值。主键是数据记录的唯一标识。若修改了主键的值,则可能会破坏数据的完整性

4.4 添加主键约束

  1. 在创建表时添加主键约束
CREATE TABLE 表名称(
	字段名 数据类型 primary key, #列级模式
	字段名 数据类型,
	字段名 数据类型
);
CREATE TABLE 表名称(
	字段名 数据类型,
	字段名 数据类型,
	字段名 数据类型,
	[constraint 约束名] primary key(字段名) #表级模式
);

CREATE TABLE test3(
	id INT PRIMARY KEY, 列级约束
	last_name VARCHAR(15),
	salary DECIMAL(10,2),
	email VARCHAR(25)
)


CREATE TABLE test4(
	id INT, 列级约束
	last_name VARCHAR(15),
	salary DECIMAL(10,2),
	email VARCHAR(25),
	表级约束
	[CONSTRAINT pk_test4_id] PRIMARY KEY(id)  没有必要起名字,无作用
)
  1. 修改表时,添加/删除主键约束
ALTER TABLE 表名称 
ADD PRIMARY KEY(字段列表); 字段列表可以是一个字段,也可以是多个字段,如果是多个字段的话,是复合主键

CREATE TABLE test5(
	id INT, 列级约束
	last_name VARCHAR(15),
	salary DECIMAL(10,2),
	email VARCHAR(25)
);


添加主键
ALTER TABLE test5
ADD PRIMARY KEY (id,last_name);

ALTER TABLE test5
ADD PRIMARY KEY (id);

删除主键
ALTER TABLE test5
DROP PRIMARY KEY;

4.5 复合主键

create table 表名称(
	字段名 数据类型,
	字段名 数据类型,
	字段名 数据类型,
	primary key(字段名1,字段名2) 表示字段1和字段2的组合是唯一的,也可以有更多个字段
);
--------------------------------------------------------------
CREATE TABLE `user1`(
	id INT, 列级约束
	`name` VARCHAR(15),
	`password` VARCHAR(25),
	表级约束
	PRIMARY KEY(`name`,`password`)  没有必要起名字,无作用
);

INSERT INTO user1
VALUES(1,'Tom','abc');

INSERT INTO `user1`
VALUES(1,'Tom1','abc');

复合的主键约束,这些列值都不允许为空
> 1048 - Column 'name' cannot be null
INSERT INTO `user1`
VALUES(1,NULL,'abc');

4.6 删除主键约束

ALTER TABLE 表名 DROP PRIMARY KEY

说明:删除主键约束,不需要指定主键名,因为一个表只有一个主键,删除主键约束后,非空还存在。

5. 自增列:AUTO_INCREMENT

5.1 作用

某个字段的值自增

5.2 关键字

AUTO_INCREMENT

5.3 特点和要求

  1. 一个表最多只可有一个自增列
  2. 当需要顺序值或唯一标识时,可设置自增长
  3. 自增长列必须是主键列/唯一键列
  4. 自增约束的列必须是整数类型
  5. 若指定添加 0 或 null 值,则会在最大字段值上自增,而不会插入 0 或 null 值;若手动添加了 具体值 ,则赋值就赋具体值

5.4 如何指定自增约束

  1. 建表时
create table 表名称(
	字段名 数据类型 primary key auto_increment,
	字段名 数据类型 unique key not null,
	字段名 数据类型 unique key,
	字段名 数据类型 not null default 默认值,
);
create table 表名称(
	字段名 数据类型 default 默认值 ,
	字段名 数据类型 unique key auto_increment,
	字段名 数据类型 not null default 默认值,,
	primary key(字段名)
);
----------------------------------------------------
CREATE TABLE test6(
	id INT PRIMARY KEY AUTO_INCREMENT,
	last_name VARCHAR(15)
);


mysql> desc employee;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| eid   | int(11)     | NO   | PRI | NULL    | auto_increment |
| ename | varchar(20) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
  1. 修改表时
    alter table 表名 modify 字段名 数据类型 auto_increment;

5.5 删除自增约束

alter table 表名称 modify 字段名 数据类型; #去掉auto_increment相当于删除

6. MySQL 8.0 新特性-自增变量的持久化

在 MySQL 8.0 之前,自增主键 AUTO_INCREMENT 的值若 大于 max(primary key) + 1,则在其重启后,会重置 AUTO_INCREMENT=max(primary key)+1。

这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。

测试:

CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT
);

插入4个空值,执行如下:
INSERT INTO test1
VALUES(0),(0),(0),(0);

查询数据表test1中的数据,结果如下:
mysql> SELECT * FROM test1;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
+----+
4 rows in set (0.00 sec)

删除id为4的记录,语句如下:
DELETE FROM test1 WHERE id = 4;

再次插入一个空值,语句如下:
INSERT INTO test1 VALUES(0);

查询此时数据表test1中的数据,结果如下:
mysql> SELECT * FROM test1;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 5 |
+----+
4 rows in set (0.00 sec)

从结果可以看出,虽然删除了id为4的记录,但是再次插入空值时,并没有重用被删除的4,而是分配了
5。 删除id为5的记录,结果如下:
DELETE FROM test1 where id=5;

重启数据库,重新插入一个空值。

INSERT INTO test1 values(0);
再次查询数据表test1中的数据,结果如下:
mysql> SELECT * FROM test1;
+----+
| id |
+----+
| 1  |
| 2  |
| 3  |
| 4  |
+----+
4 rows in set (0.00 sec)

从结果可以看出,新插入的0值分配的是4,按照重启前的操作逻辑,此处应该分配6。出现上述结果的主要原因是自增主键没有持久化。 在MySQL 5.7系统中,对于自增主键的分配规则,是由InnoDB数据字典内部一个 计数器 来决定的,而该计数器只在 内存中维护 ,并不会持久化到磁盘中。当数据库重启时,该计数器会被初始化

在MySQL 8.0版本中,上述测试步骤最后一步的结果如下:

mysql> SELECT * FROM test1;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 6 |
+----+
4 rows in set (0.00 sec)

从结果可以看出,自增变量已经持久化了。
MySQL 8.0将自增主键的计数器持久化到 重做日志 中。每次计数器发生改变,都会将其写入重做日志中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。

6. FOREIGN KEY 约束

6.1 作用

限制表中某个字段的引用完整性

例如:员工表中的员工所在部门的id,必须在部门表中可以找到此 id

Snipaste_2022-06-21_21-47-56

6.2 关键字

FOREIGN KEY

6.3 主表和从表/父表和子表

主表(父表):被引用的表,被参考的表
从表(子表):引用别的表,参考别的表
例如:员工表的员工所在部门这个字段的值要参考部门表:部门表是主表,员工表是从表。

6.4 特点

  1. 从表的外键列,必须引用/参考主表的主键唯一约束的列
  • 主表中 被依赖/参考 的值必须是唯一的
  1. 在创建外键约束时,若不显式的给外键约束命名,则自动生成一个外键名(不是列名),也可显式的指定外键约束名
  2. 若要在创建表时就指定外键约束列,应先创建主表,后创建从表
  3. 删除表时,应先删除从表(或外键约束),再删除主表
  4. 当主表的值被从表所参照时,主表的记录不允许删除,若要删除数据。应该先删除从表中依赖主表的数据,后才可删除主表的数据
  5. 在从表中指定外键约束,一个表可以建立多个外键约束
  6. 从表的外键列和主表中的被参照的列名可以不相同,但是数据类型必须一致,逻辑意义也需一致。
  7. 当创建外键约束时,系统会默认在所在列上创建对应的普通索引,索引名时外键约束名。(根据外键查询效率较高)
  8. 删除外键约束后,必须手动删除对应索引

6.5 添加外键约束

  1. 创建表时
CREATE TABLE 主表名称(
	字段1 数据类型 PRIMARY KEY,
	字段2 数据类型
);

CREATE TABLE 从表名称(
	字段1 数据类型 PRIMARY KEY,
	字段2 数据类型,
	[CONSTRAINT <外键约束名>] FOREIGN KEY (从表字段) references 主表名称(主表字段)
)

(从表的某个字段)的数据类型必须与主表名(被参考字段)的数据类型一致,逻辑意义也一样
(从表的某个字段)的字段名可以与主表名(被参考字段)的字段名一样,也可以不一样
FOREIGN KEY: 在表级指定子表中的列
REFERENCES: 标示在父表中的列
create table dept( #主表
	did int primary key, #部门编号
	dname varchar(50) #部门名称
);
create table emp(#从表
	eid int primary key, #员工编号
	ename varchar(5), #员工姓名
	deptid int, #员工所在的部门
	foreign key (deptid) references dept(did) #在从表中指定外键约束
	#emp表的deptid和和dept表的did的数据类型一致,意义都是表示部门的编号
);
说明:
(1)主表dept必须先创建成功,然后才能创建emp表,指定外键成功。
(2)删除表时,先删除从表emp,再删除主表dept
  1. 修改表时
ALTER TABLE 从表名 ADDADD [CONSTRAINT 约束名] FOREIGN KEY (从表的字段) REFERENCES 主表名(被引用字段) [on update xx][on delete xx];

ALTER TABLE emp1
ADD [CONSTRAINT emp_dept_id_fk] FOREIGN KEY(dept_id) REFERENCES dept(dept_id)

总结:约束关系是同时针对主表和从表的

  • 添加了外键约束后,主表的修改和删除数据受约束
  • 添加了外键约束后,从表的添加和修改数据受约束
  • 在从表上建立外键时,主表必须存在
  • 删除主表时,要求从表先删除,或将从表上外键引用主表的关系删除

6.7 约束等级

  • Cascade方式:在主表上update/delete 时,同步 update/delete 从表中的对应记录
  • Set null方式:在主表上 update/ delete 时,从表中对应的记录的列值设置为 null(前提是:从表的外键列不可为 not null)
  • No action 方式:若从表中有匹配的记录,则不允许对主表对应列进行 update/delete 操作
  • Restrict方式:和 no action一致,都是立即检查外键约束
  • Set default 方式:主表有变更时,从表的将外键列设置成一个默认的值,但Innodb不能识别

注意:若无显式指定,则默认为 Restrict 方式

对于外键约束,最好是采用: ON UPDATE CASCADE ON DELETE RESTRICT 的方式。

create table dept(
	did int primary key, #部门编号
	dname varchar(50) #部门名称
);
create table emp(
	eid int primary key, #员工编号
	ename varchar(5), #员工姓名
	deptid int, #员工所在的部门
	foreign key (deptid) references dept(did) on update cascade on delete set null
	#把修改操作设置为级联修改等级,把删除操作设置为set null等级
);

insert into dept values(1001,'教学部');
insert into dept values(1002, '财务部');
insert into dept values(1003, '咨询部');

insert into emp values(1,'张三',1001); #在添加这条记录时,要求部门表有1001部门
insert into emp values(2,'李四',1001);
insert into emp values(3,'王五',1002);

mysql> select * from dept;

mysql> select * from emp;

#修改主表成功,从表也跟着修改,修改了主表被引用的字段1002为1004,从表的引用字段就跟着修改为1004了
mysql> update dept set did = 1004 where did = 1002;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from dept;
+------+--------+
| did | dname |
+------+--------+
| 1001 | 教学部 |
| 1003 | 咨询部 |
| 1004 | 财务部 | #原来是1002,修改为1004
+------+--------+
3 rows in set (0.00 sec)
mysql> select * from emp;
+-----+-------+--------+
| eid | ename | deptid |
+-----+-------+--------+
| 1 | 张三 | 1001 |
| 2 | 李四 | 1001 |
| 3 | 王五 | 1004 | #原来是1002,跟着修改为1004
+-----+-------+--------+
3 rows in set (0.00 sec)

#删除主表的记录成功,从表对应的字段的值被修改为null
mysql> delete from dept where did = 1001;
Query OK, 1 row affected (0.01 sec)
mysql> select * from dept;
+------+--------+
| did | dname | #记录1001部门被删除了
+------+--------+
| 1003 | 咨询部 |
| 1004 | 财务部 |
+------+--------+
2 rows in set (0.00 sec)
mysql> select * from emp;
+-----+-------+--------+
| eid | ename | deptid |
+-----+-------+--------+
| 1   | 张三  | NULL   | #原来引用1001部门的员工,deptid字段变为null
| 2   | 李四  | NULL   |
| 3   | 王五  | 1004   |
+-----+-------+--------+
3 rows in set (0.00 sec)

6.8 删除外键约束

(1)第一步先查看约束名和删除外键约束
SELECT * FROM information_schema.table_constraints 
WHERE table_name = '表名称';#查看某个表的约束名

ALTER TABLE 从表名 DROP FOREIGN KEY 外键约束名;


(2)第二步查看索引名和删除索引。(注意,只能手动删除)
SHOW INDEX FROM 表名称; #查看某个表的索引名
ALTER TABLE 从表名 DROP INDEX 索引名;

6.9 开发场景

问题1:如果两个表之间有关系(一对一、一对多),比如:员工表和部门表(一对多),它们之间是否一定要建外键约束?
答:不是的

问题2:建和不建外键约束有什么区别?
答:建外键约束,你的操作(创建表、删除表、添加、修改、删除)会受到限制,从语法层面受到限制。例如:在员工表中不可能添加一个员工信息,它的部门的值在部门表中找不到。

不建外键约束,你的操作(创建表、删除表、添加、修改、删除)不受限制,要保证数据的引用完整性,只能依 靠程序员的自觉 ,或者是 在Java程序中进行限定 。例如:在员工表中,可以添加一个员工的信息,它的部门指定为一个完全不存在的部门。

问题3:那么建和不建外键约束和查询有没有关系?
答:没有

在 MySQL 里,外键约束是有成本的,需要消耗系统资源。对于大并发的 SQL 操作,有可能会不适合。比如大型网站的中央数据库,可能会 因为外键约束的系统开销而变得非常慢 。所以, MySQL 允许你不使用系统自带的外键约束,在 应用层面 完成检查数据一致性的逻辑。也就是说,即使你不用外键约束,也要想办法通过应用层面的附加逻辑,来实现外键约束的功能,确保数据的一致性。

6.10 开发规范

强制 】不得使用外键与级联,一切外键概念必须在应用层解决。
说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学
生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于 单机低并发 ,不适合 分布式 、 高并发集群 ;级联更新是强阻塞,存在数据库 更新风暴 的风险;外键影响数据库的插入速度

7. CHECK 约束

7.1 作用

限制某个字段的范围

7.2 关键字

CHECK

7.3 MySQL 5.7 不支持

MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警

但是MySQL 8.0中可以使用check约束了

CREATE TABLE test10(
	id INT,
	last_name VARCHAR(15),
	salary DECIMAL(10,2) CHECK (salary > 2000)
);
 
INSERT INTO test10
VALUES(1,'Tom',2500);

添加失败
> 3819 - Check constraint 'test10_chk_1' is violated.
INSERT INTO test10
VALUES(2,'Tom1',1500);

8. DEFAULT 约束

8.1 作用

给某个字段指定默认值,一旦设置默认值,若插入数据时,没有显式的赋值,则赋默认值

8.2 关键字

DEFAULT

8.3 如何添加默认约束

  1. 建表时
create table 表名称(
	字段名 数据类型 primary key,
	字段名 数据类型 unique key not null,
	字段名 数据类型 unique key,
	字段名 数据类型 not null default 默认值,
);

create table 表名称(
	字段名 数据类型 default 默认值 ,
	字段名 数据类型 not null default 默认值,
	字段名 数据类型 not null default 默认值,
	primary key(字段名),
	unique key(字段名)
);

说明:默认值约束一般不在唯一键和主键列上加

create table employee(
	eid int primary key,
	ename varchar(20) not null,
	gender char default '男',
	tel char(11) not null default '' #默认是空字符串
);
  1. 修改表
alter table 表名称 modify 字段名 数据类型 default 默认值;
如果这个字段原来有非空约束,你还保留非空约束,那么在加默认值约束时,还得保留非空约束,否则非空约束就被删除了
同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默
认值约束,否则就删除了
alter table 表名称 modify 字段名 数据类型 default 默认值 not null;

8.4 删除默认值约束

alter table 表名称 modify 字段名 数据类型 ;#删除默认值约束,也不保留非空约束

alter table 表名称 modify 字段名 数据类型 not null; #删除默认值约束,保留非空约束

9. 面试

面试1、为什么建表时,加 not null default ‘’ 或 default 0
答:不想让表中出现null值。

面试2、为什么不想要 null 的值
答:(1)不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
(2)效率不高。影响提高索引效果。因此,我们往往在建表时 not null default ‘’ 或 default 0

面试3、带AUTO_INCREMENT约束的字段值是从1开始的吗?

在MySQL中,默认AUTO_INCREMENT的初始值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。

递增的值是根据字段中最大的值开始递增的。

面试4、并不是每个表都可以任意选择存储引擎? 外键约束(FOREIGN KEY)不能跨引擎使用
MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的。

文章作者: 临川
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 临川羡鱼
MySQL MySQL
喜欢就支持一下吧