当前位置: 首页 > news >正文

MySQL | 尚硅谷 | 第13章_约束

MySQL笔记:第13章_约束

文章目录

  • MySQL笔记:第13章_约束
        • 第13章_约束
      • 1. 约束(constraint)概述
          • 1.1 为什么需要约束
          • 1.2 什么是约束
          • 1.3 约束的分类
          • 演示代码
      • 2. 非空约束
          • 2.1 作用
          • 2.2 关键字
          • 2.3 特点
          • 2.4 添加非空约束
          • 2.5 删除非空约束
          • 演示代码
      • 3. 唯一性约束
          • 3.1 作用
          • 3.2 关键字
          • 3.3 特点
          • 3.4 添加唯一约束
          • 3.5 关于复合唯一约束
          • 3.5 删除唯一约束
          • 演示代码
      • 4. PRIMARY KEY 约束
          • 4.1 作用
          • 4.2 关键字
          • 4.3 特点
          • 4.4 添加[主键约束](https://so.csdn.net/so/search?q=主键约束&spm=1001.2101.3001.7020)
          • 4.5 关于复合主键
            • 4.6 删除主键约束
          • 演示代码
      • 5. 自增列:AUTO_INCREMENT
          • 5.1 作用
          • 5.2 关键字
          • 5.3 特点和要求
          • 5.4 如何指定自增约束
          • 5.5 如何删除自增约束
          • 5.6 MySQL 8.0新特性—自增变量的持久化
          • 演示代码
      • 6. FOREIGN KEY 约束
          • 6.1 作用
          • 6.2 关键字
          • 6.3 主表和从表/父表和子表
          • 6.4 特点
          • 6.5 添加外键约束
          • 6.6 演示问题
          • 6.7 约束等级
          • 6.8 删除外键约束
          • 6.9 开发场景
          • 6.10 阿里开发规范
          • 演示代码
      • 7. CHECK 约束
          • 7.1 作用
          • 7.2 关键字
          • 7.3 说明:MySQL 5.7 不支持
          • 演示代码
      • 8. DEFAULT约束
          • 8.1 作用
          • 8.2 关键字
          • 8.3 如何给字段加默认值
          • 8.4 如何删除默认值约束
          • 演示代码
      • 9. 面试
      • 课后练习

第13章_约束

1. 约束(constraint)概述

1.1 为什么需要约束

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

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

  • 实体完整性(Entity Integrity) :例如,同一个表中,不能存在两条完全相同无法区分的记录
  • 域完整性(Domain Integrity) :例如:年龄范围0-120,性别范围“男/女”
  • 引用完整性(Referential Integrity):例如:员工所在部门,在部门表中要能找到这个部门 用户
  • 自定义完整性(User-defined Integrity):例如:用户名唯一、密码不能为空等,本部门经理的工资不得高于本部门职工的平均工资的5倍。
1.2 什么是约束

约束是表级的强制规定。

可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束。

1.3 约束的分类

根据约束数据列的限制,约束可分为:

  • 单列约束:每个约束只约束一列
  • 多列约束:每个约束可约束多列数据

根据约束的作用范围,约束可分为:

  • 列级约束:只能作用在一个列上,跟在列的定义后面
  • 表级约束:可以作用在多个列上,不与列一起,而是单独定义
.位置支持的约束类型是否可以起约束名
列级约束列的后面语法都支持,但外键没有效果不可以
表级约束所有列的下面默认和非空不支持,其他支持可以(主键没有效果)

根据约束起的作用,约束可分为:

  • NOT NULL 非空约束,规定某个字段不能为空
  • UNIQUE 唯一约束,规定某个字段在整个表中是唯一的
  • PRIMARY KEY 主键(非空且唯一)约束
  • FOREIGN KEY 外键约束
  • CHECK 检查约束
  • DEFAULT 默认值约束

注意: MySQL不支持check约束,但可以使用check约束,而没有任何效果

查看某个表已有的约束

#information_schema数据库名(系统库)
#table_constraints表名称(专门存储各个表的约束)
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';
演示代码
/*
1. 基础知识
1.1 为什么需要约束? 为了保证数据的完整性!1.2 什么叫约束?对表中字段的限制。1.3 约束的分类:角度1:约束的字段的个数
单列约束 vs 多列约束角度2:约束的作用范围列级约束:将此约束声明在对应字段的后面
表级约束:在表中所有字段都声明完,在所有字段的后面声明的约束角度3:约束的作用(或功能)① not null (非空约束)
② unique  (唯一性约束)
③ primary key (主键约束)
④ foreign key (外键约束)
⑤ check (检查约束)
⑥ default (默认值约束)1.4 如何添加/删除约束?CREATE TABLE时添加约束ALTER TABLE 时增加约束、删除约束*/#2. 如何查看表中的约束
SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'employees';
/*
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | atguigudb         | emp_email_uk    | atguigudb    | employees  | UNIQUE          | YES      |
| def                | atguigudb         | emp_emp_id_pk   | atguigudb    | employees  | UNIQUE          | YES      |
| def                | atguigudb         | PRIMARY         | atguigudb    | employees  | PRIMARY KEY     | YES      |
| def                | atguigudb         | emp_dept_fk     | atguigudb    | employees  | FOREIGN KEY     | YES      |
| def                | atguigudb         | emp_job_fk      | atguigudb    | employees  | FOREIGN KEY     | YES      |
| def                | atguigudb         | emp_manager_fk  | atguigudb    | employees  | FOREIGN KEY     | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
*/

2. 非空约束

2.1 作用

限定某个字段/某列的值不允许为空

2.2 关键字

NOT NULL

2.3 特点
  • 默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
  • 非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
  • 一个表可以有很多列都分别限定了非空
  • 空字符串’'不等于NULL,0也不等于NULL
2.4 添加非空约束

(1)建表时

CREATE TABLE 表名称(
字段名	数据类型,
字段名	数据类型 NOT NULL,
字段名	数据类型 NOT NULL
);

举例:

CREATE TABLE emp(
id INT(10) NOT NULL,
NAME VARCHAR(20) NOT NULL,
sex CHAR NULL
);CREATE TABLE student(
sid int,
sname varchar(20) not null,
tel char(11) ,
cardid char(18) not null
);insert into student values(1,'张三','13710011002','110222198912032545'); #成功insert into student values(2,'李四','13710011002',null);#身份证号为空 ERROR 1048 (23000): Column 'cardid' cannot be nullinsert into student values(2,'李四',null,'110222198912032546');#成功,tel允许为空insert into student values(3,null,null,'110222198912032547');#失败 ERROR 1048 (23000): Column 'sname' cannot be null

(2)建表后

alter table 表名称 modify 字段名 数据类型 not null;

举例:

ALTER TABLE emp
MODIFY sex VARCHAR(30) NOT NULL;
alter table student modify sname varchar(20) not null;
2.5 删除非空约束
alter table 表名称 modify 字段名 数据类型 NULL;
#去掉not null,相当于修改某个非注解字段,该字段允许为空

alter table 表名称 modify 字段名 数据类型;
#去掉not null,相当于修改某个非注解字段,该字段允许为空

举例:

ALTER TABLE emp
MODIFY sex VARCHAR(30) NULL;ALTER TABLE emp
MODIFY NAME VARCHAR(15) DEFAULT 'abc' NULL;
演示代码
CREATE DATABASE dbtest13;
USE dbtest13;
#2. not null (非空约束)
#限定某个字段/某列的值不允许为空
#3.1 在CREATE TABLE时添加约束CREATE TABLE test1(
id INT NOT NULL,
last_name VARCHAR(15) NOT NULL,
email VARCHAR(25),
salary DECIMAL(10,2));DESC test1;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   |     | NULL    |       |
| last_name | varchar(15)   | NO   |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/INSERT INTO test1(id,last_name,email,salary)
VALUES(1,'Tom','tom@126.com',3400);#错误:Column 'last_name' cannot be null
INSERT INTO test1(id,last_name,email,salary)
VALUES(2,NULL,'tom1@126.com',3400);#错误:Column 'id' cannot be null
INSERT INTO test1(id,last_name,email,salary)
VALUES(NULL,'Jerry','jerry@126.com',3400);
#错误:Field 'last_name' doesn't have a default value
INSERT INTO test1(id,email)
VALUES(2,'abc@126.com');#错误:Column 'last_name' cannot be null
UPDATE test1
SET last_name = NULL
WHERE id = 1;UPDATE test1
SET email = 'tom@126.com'
WHERE id = 1;
#结论:约束的存在会对增删改等操作产生影响#3.2 在ALTER TABLE时添加约束
SELECT * FROM test1;
/*
+----+-----------+-------------+---------+
| id | last_name | email       | salary  |
+----+-----------+-------------+---------+
|  1 | Tom       | tom@126.com | 3400.00 |
+----+-----------+-------------+---------+
*/
DESC test1;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   |     | NULL    |       |
| last_name | varchar(15)   | NO   |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/ALTER TABLE test1
MODIFY email VARCHAR(25) NOT NULL;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   |     | NULL    |       |
| last_name | varchar(15)   | NO   |     | NULL    |       |
| email     | varchar(25)   | NO   |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/#3.3 在ALTER TABLE时删除约束
ALTER TABLE test1
MODIFY email VARCHAR(25) NULL;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889

3. 唯一性约束

3.1 作用

用来限制某个字段/某列的值不能重复。

3.2 关键字

UNIQUE

3.3 特点
  • 同一个表可以有多个唯一约束。
  • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。
  • 唯一性约束允许列值为空。
  • 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。
  • MySQL会给唯一约束的列上默认创建一个唯一索引。
3.4 添加唯一约束

(1)建表时

create table 表名称(
字段名	数据类型,
字段名	数据类型 unique,
字段名	数据类型 unique key,
字段名 数据类型
);create table 表名称(
字段名	数据类型,
字段名	数据类型,
字段名	数据类型,
[constraint 约束名] unique key(字段名)
);

举例:

create table student(
sid int,
sname varchar(20),
tel char(11) unique,
cardid char(18) unique key
);CREATE TABLE t_course(
cid INT UNIQUE,
cname VARCHAR(100) UNIQUE,
description VARCHAR(200)
);CREATE TABLE USER(
id INT NOT NULL,
NAME VARCHAR(25),
PASSWORD VARCHAR(16),
--	使用表级约束语法
CONSTRAINT uk_name_pwd UNIQUE(NAME,PASSWORD)
);

表示用户名和密码组合不能重复

insert into student values(1,'张三','13710011002','101223199012015623'); insert into student values(2,'李四','13710011003','101223199012015624');select *from student;	
/*
+	-----	+-------	+-------------	+--------------------	+
| sid |	sname |	tel	| cardid	|
+	-----	+-------	+-------------	+--------------------	+
|	1	|	张三	| 13710011002	| 101223199012015623 |
|	2	|	李四	| 13710011003	| 101223199012015624 |
+	-----	+-------	+-------------	+--------------------	+
*/insert into student values(3,'王五','13710011004','101223199012015624'); #身份证号重复 ERROR 1062 (23000): Duplicate entry '101223199012015624' for key 'cardid'insert into student values(3,'王五','13710011003','101223199012015625'); ERROR 1062 (23000): Duplicate entry '13710011003' for key 'tel'

(2)建表后指定唯一键约束

#字段列表中如果是一个字段,表示该列的值唯一。
#如果是两个或更多个字段,那么复合唯一,
#即多个字段的组合是唯一的
#方式1:
alter table 表名称 add unique key(字段列表);#方式2:
alter table 表名称 modify 字段名 字段类型 unique;

举例:

ALTER TABLE USER
ADD UNIQUE(NAME,PASSWORD);ALTER TABLE USER
ADD CONSTRAINT uk_name_pwd UNIQUE(NAME,PASSWORD);ALTER TABLE USER
MODIFY NAME VARCHAR(20) UNIQUE;

举例:

create table student(
sid int primary key,
sname varchar(20),
tel char(11) ,
cardid char(18)
);alter table student add unique key(tel);
alter table student add unique key(cardid);
3.5 关于复合唯一约束
create table 表名称(
字段名	数据类型,
字段名	数据类型,
字段名	数据类型,
unique key(字段列表) 
#字段列表中写的是多个字段名,多个字段名用逗号分隔表示
#那么是复合唯一,即多个字段的组合是唯一的
);#学生表
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');#成功select * from student;/*
+	-----	+-------		+-------------	+--------------------	+
| sid |	sname | tel	| cardid	|
+	-----	+-------	+-------------	+--------------------	+
|	1 |	张三	| 13710011002 | 101223199012015623 |
|	2 |	李四	| 13710011003 | 101223199012015624 |
+	-----	+-------	+-------------	+--------------------	+
*/	
select * from course;	
/*	
+	------	+	-------	+		
| cid	|	cname |		
+	------	+	-------	+		
| 1001	|	Java	|		
| 1002	|	MySQL |		
+	------	+	-------	+		
*/					
insert into student_course values
(1, 1, 1001, 89),
(2, 1, 1002, 90),
(3, 2, 1001, 88),
(4, 2, 1002, 56);#成功select	* from	student_course;
/*
+	----	+------	+------	+-------	+
| id |	sid	|	cid	|	score	|
+	----	+------	+------	+-------	+
|	1	|	1	|	1001	|	89	|
|	2	|	1	|	1002	|	90	|
|	3	|	2	|	1001	|	88	|
|	4	|	2	|	1002	|	56	|
+	----	+------	+------	+-------	+
*/
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 表名称; 查看表的索引

演示代码
#3. unique  (唯一性约束)
#用来限制某个字段/某列的值不能重复。
#3.1 在CREATE TABLE时添加约束
CREATE TABLE test2(
id INT UNIQUE, #列级约束
last_name VARCHAR(15) ,
email VARCHAR(25),
salary DECIMAL(10,2),
#表级约束
CONSTRAINT uk_test2_email UNIQUE(email)#uk_test2_email为email的约束名
);DESC test2;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  | UNI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  | UNI | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/
SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'test2';
/*
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | dbtest13          | id              | dbtest13     | test2      | UNIQUE          | YES      |
| def                | dbtest13          | uk_test2_email  | dbtest13     | test2      | UNIQUE          | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
*/
#在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。
INSERT INTO test2(id,last_name,email,salary)
VALUES(1,'Tom','tom@126.com',4500);#错误:Duplicate entry '1' for key 'test2.id'
INSERT INTO test2(id,last_name,email,salary)
VALUES(1,'Tom1','tom1@126.com',4600);#错误:Duplicate entry 'tom@126.com' for key 'test2.uk_test2_email'
INSERT INTO test2(id,last_name,email,salary)
VALUES(2,'Tom1','tom@126.com',4600);#可以向声明为unique的字段上添加null值。而且可以多次添加null
INSERT INTO test2(id,last_name,email,salary)
VALUES(2,'Tom1',NULL,4600);INSERT INTO test2(id,last_name,email,salary)
VALUES(3,'Tom2',NULL,4600);SELECT * FROM test2;
/*
+------+-----------+-------------+---------+
| id   | last_name | email       | salary  |
+------+-----------+-------------+---------+
|    1 | Tom       | tom@126.com | 4500.00 |
|    2 | Tom1      | NULL        | 4600.00 |
|    3 | Tom2      | NULL        | 4600.00 |
+------+-----------+-------------+---------+
*/#3.2 在ALTER TABLE时添加约束
DESC test2;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  | UNI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  | UNI | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/UPDATE test2
SET salary = 5000
WHERE id = 3;
#方式1:
ALTER TABLE test2
ADD CONSTRAINT uk_test2_sal UNIQUE(salary);
#方式2:
ALTER TABLE test2
MODIFY last_name VARCHAR(15) UNIQUE;
DESC test2;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  | UNI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  | UNI | NULL    |       |
| salary    | decimal(10,2) | YES  | UNI | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/#3.3 复合的唯一性约束
CREATE TABLE USER(
id INT,
`name` VARCHAR(15),
`password` VARCHAR(25),#表级约束
CONSTRAINT uk_user_name_pwd UNIQUE(`name`,`password`)#`name` 和`password`不同时一样即可
);INSERT INTO USER
VALUES(1,'Tom','abc');
#可以成功的:
INSERT INTO USER
VALUES(1,'Tom1','abc');SELECT *
FROM USER;
/*
+------+------+----------+
| id   | name | password |
+------+------+----------+
|    1 | Tom  | abc      |
|    1 | Tom1 | abc      |
+------+------+----------+
*/#案例:复合的唯一性约束的案例
#学生表
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');#成功SELECT * FROM student;
/*
+------+--------+-------------+--------------------+
| sid  | sname  | tel         | cardid             |
+------+--------+-------------+--------------------+
|    1 | 张三   | 13710011002 | 101223199012015623 |
|    2 | 李四   | 13710011003 | 101223199012015624 |
+------+--------+-------------+--------------------+
*/SELECT * FROM course;
/*
+------+-------+
| cid  | cname |
+------+-------+
| 1001 | Java  |
| 1002 | MySQL |
+------+-------+
*/INSERT INTO student_course VALUES
(1, 1, 1001, 89),
(2, 1, 1002, 90),
(3, 2, 1001, 88),
(4, 2, 1002, 56);#成功SELECT * FROM student_course;
/*
+------+------+------+-------+
| id   | sid  | cid  | score |
+------+------+------+-------+
|    1 |    1 | 1001 |    89 |
|    2 |    1 | 1002 |    90 |
|    3 |    2 | 1001 |    88 |
|    4 |    2 | 1002 |    56 |
+------+------+------+-------+
*/#错误:Duplicate entry '2-1002' for key 'student_course.sid'
INSERT INTO student_course VALUES
(5,2,1002,67);#3.4 删除唯一性约束
-- 添加唯一性约束的列上也会自动创建唯一索引。
-- 删除唯一约束只能通过删除唯一索引的方式删除。
-- 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。
-- 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'student_course';SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'test2';DESC test2;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  | UNI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  | UNI | NULL    |       |
| salary    | decimal(10,2) | YES  | UNI | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/
#如何删除唯一性索引
ALTER TABLE test2
DROP INDEX last_name;ALTER TABLE test2
DROP INDEX uk_test2_sal;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  | UNI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  | UNI | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235

4. PRIMARY KEY 约束

4.1 作用

用来唯一标识表中的一行记录。

4.2 关键字

primary key

4.3 特点
  • 主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值
    请添加图片描述
  • 一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别上创建。
  • 主键约束对应着表中的一列或者多列(复合主键)
  • 如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
  • MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
  • 当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了。
  • 需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。
4.4 添加主键约束

(1)建表时指定主键约束

create table 表名称(
字段名	数据类型 primary key, #列级模式
字段名	数据类型,
字段名 数据类型
);create table 表名称(
字段名	数据类型,
字段名	数据类型,
字段名	数据类型,
[constraint 约束名] primary key(字段名) #表级模式
);

举例:

create table temp(
id int primary key,
name varchar(20)
);
desc temp;			
/*		
+	-------	+-------------	+------	+-----	+---------	+-------	+
| Field |	Type	| Null	| Key | Default	| Extra |
+	-------	+-------------	+------	+-----	+---------	+-------	+
| id	|	int(11)	| NO	| PRI | NULL	|	|
| name	|	varchar(20) | YES	|	| NULL	|	|
+	-------	+-------------	+------	+-----	+---------	+-------	+
*/		insert into temp values(1,'张三');#成功
insert into temp values(2,'李四');#成功
select * from temp;
/*
+	----	+------	+
| id |	name |
+	----	+------	+
|	1	|	张三 |
|	2	|	李四 |
+	----	+------	+
*/insert into temp values(1,'张三');#失败
ERROR 1062 (23000): Duplicate(重复) entry(键入,输入) '1' for key 'PRIMARY'insert into temp values(1,'王五');#失败
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
insert into temp values(3,'张三');#成功select * from temp;
/*
+	----	+------	+
| id |	name |
+	----	+------	+
|	1	|	张三 |
|	2	|	李四 |
|	3	|	张三 |
+	----	+------	+
*/
insert	into temp values(4,null);#成功insert into temp values(null,'李琦');#失败 ERROR 1048 (23000): Column 'id' cannot be nullselect * from temp;
/*
+	----	+------	+
| id |	name |
+	----	+------	+
|	1	|	张三 |
|	2	|	李四 |
|	3	|	张三 |
|	4	|	NULL |
+	----	+------	+
*/#演示一个表建立两个主键约束
create table temp(
id int primary key,
name varchar(20) primary key
);
ERROR 1068 (42000): Multiple(多重的) primary key defined(定义)

再举例:

  • 列级约束
CREATE TABLE emp4(
id INT PRIMARY KEY AUTO_INCREMENT ,
NAME VARCHAR(20)
);

表级约束

CREATE TABLE emp5(
id INT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(20),
pwd VARCHAR(15),
CONSTRAINT emp5_id_pk PRIMARY KEY(id)
);

(2)建表后增加主键约束

ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表); 
#字段列表可以是一个字段,也可以是多个字段,如果是多个字段的话,是复合主键ALTER TABLE student ADD PRIMARY KEY (sid);ALTER TABLE emp5 ADD PRIMARY KEY(NAME,pwd);
4.5 关于复合主键
create table 表名称(
字段名	数据类型,
字段名	数据类型,
字段名	数据类型,
primary key(字段名1,字段名2)	#表示字段1和字段2的组合是唯一的,也可以有更多个字段
);#学生表
create table student(
sid int primary key,	#学号
sname varchar(20)	#学生姓名
);
#课程表
create table course(
cid int primary key,	#课程编号
cname varchar(20)	#课程名称
);
#选课表
create table student_course(
sid int,
cid int,
score int,
primary key(sid,cid)	#复合主键
);insert into student values(1,'张三'),(2,'李四');
insert into course values(1001,'Java'),(1002,'MySQL');
select * from student;
/*
+	-----	+-------	+
| sid |	sname |
+	-----	+-------	+
|	1 |	张三	|
|	2 |	李四	|
+	-----	+-------	+
*/
select * from course;
/*
+	------	+	-------	+
| cid	|	cname |
+	------	+	-------	+
| 1001	|	Java	|
| 1002	|	MySQL |
+	------	+	-------	+
*/insert into student_course values(1, 1001, 89),(1,1002,90),(2,1001,88),(2,1002,56);select * from	student_course;/*
+	-----	+------	+-------	+
| sid |	cid	| score	|
+	-----	+------	+-------	+
|	1	|	1001	|	89	|
|	1	|	1002	|	90	|
|	2	|	1001	|	88	|
|	2	|	1002	|	56	|
+	-----	+------	+-------	+
*/insert into student_course values(1, 1001, 100);
ERROR 1062 (23000): Duplicate entry '1-1001' for key 'PRIMARY'desc student_course;		
/*		
+-------	+---------	+------	+-----	+---------	+-------	+
| Field |	Type	|	Null |	Key |	Default | Extra |
+-------	+---------	+------	+-----	+---------	+-------	+
| sid	|	int(11) |	NO	|	PRI |	NULL	|	|
| cid	|	int(11) |	NO	|	PRI |	NULL	|	|
| score |	int(11) |	YES	|	|	NULL	|	|
+-------	+---------	+------	+-----	+---------	+-------	+
*/		

再举例

CREATE TABLE emp6(
id INT NOT NULL,
NAME VARCHAR(20),
pwd VARCHAR(15),
CONSTRAINT emp7_pk PRIMARY KEY(NAME,pwd)
);
4.6 删除主键约束
alter table 表名称 drop primary key;

举例:

ALTER TABLE student DROP PRIMARY KEY;ALTER TABLE emp5 DROP PRIMARY KEY;

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

演示代码
#4. primary key (主键约束)
#用来唯一标识表中的一行记录。
#主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。
#4.1 在CREATE TABLE时添加约束
#一个表中最多只能有一个主键约束。#错误:Multiple primary key defined
CREATE TABLE test3(
id INT PRIMARY KEY, #列级约束
last_name VARCHAR(15) PRIMARY KEY,
salary DECIMAL(10,2),
email VARCHAR(25)
);# 主键约束特征:非空且唯一,用于唯一的标识表中的一条记录。
CREATE TABLE test4(
id INT PRIMARY KEY, #列级约束
last_name VARCHAR(15),
salary DECIMAL(10,2),
email VARCHAR(25)
);#MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
CREATE TABLE test5(
id INT , 
last_name VARCHAR(15),
salary DECIMAL(10,2),
email VARCHAR(25),
#表级约束
CONSTRAINT pk_test5_id PRIMARY KEY(id)  #没有必要起名字(起不起主键的名字都是PRIMARY)
);SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'test5';INSERT INTO test4(id,last_name,salary,email)
VALUES(1,'Tom',4500,'tom@126.com');#错误:Duplicate entry '1' for key 'test4.PRIMARY'
INSERT INTO test4(id,last_name,salary,email)
VALUES(1,'Tom',4500,'tom@126.com');#错误:Column 'id' cannot be null
INSERT INTO test4(id,last_name,salary,email)
VALUES(NULL,'Tom',4500,'tom@126.com');SELECT * FROM test4;
/*
+----+-----------+---------+-------------+
| id | last_name | salary  | email       |
+----+-----------+---------+-------------+
|  1 | Tom       | 4500.00 | tom@126.com |
+----+-----------+---------+-------------+
*/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');
#错误:Column 'name' cannot be null
INSERT INTO user1
VALUES(1,NULL,'abc');SELECT * FROM user1;
/*
+------+------+----------+
| id   | NAME | PASSWORD |
+------+------+----------+
|    1 | Tom  | abc      |
+------+------+----------+
*/#4.2 在ALTER TABLE时添加约束CREATE TABLE test6(
id INT ,
last_name VARCHAR(15),
salary DECIMAL(10,2),
email VARCHAR(25)
);DESC test6;
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  |     | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/
ALTER TABLE test6
ADD PRIMARY KEY (id);
/*
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   | PRI | NULL    |       |
| last_name | varchar(15)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
*/
#4.3 如何删除主键约束 (在实际开发中,不会去删除表中的主键约束!)
ALTER TABLE test6
DROP PRIMARY KEY;

5. 自增列:AUTO_INCREMENT

5.1 作用

某个字段的值自增

5.2 关键字

auto_increment

5.3 特点和要求

(1)一个表最多只能有一个自增长列
(2)当需要产生唯一标识符或顺序值时,可设置自增长
(3)自增长列约束的列必须是键列(主键列,唯一键列)
(4)自增约束的列的数据类型必须是整数类型
(5)如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。

错误演示:

create table employee(
eid int auto_increment,
ename varchar(20)
);
#	ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
create table employee(
eid int primary key,
ename varchar(20) unique key auto_increment
);
#ERROR 1063 (42000): Incorrect column specifier for column 'ename'  因为ename不是整数类型
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 employee(
eid int primary key auto_increment,
ename varchar(20)
);
desc employee;			
/*			
+	-------	+-------------	+------	+-----	+---------	+----------------	+
| Field |	Type	| Null	| Key | Default |	Extra	|
+	-------	+-------------	+------	+-----	+---------	+----------------	+
| eid	|	int(11)	| NO	| PRI | NULL	|	auto_increment |
| ename |	varchar(20)	| YES	|	| NULL	|		|
+	-------	+-------------	+------	+-----	+---------	+----------------	+
*/		

(2)建表后

alter table 表名称 modify 字段名 数据类型 auto_increment;

例如:

create table employee(
eid int primary key ,
ename varchar(20)
);alter table employee modify eid int auto_increment;
desc employee;			
/*			
+	-------	+-------------	+------	+-----	+---------	+----------------	+
| Field |	Type	| Null	| Key | Default |	Extra	|
+	-------	+-------------	+------	+-----	+---------	+----------------	+
| eid	|	int(11)	| NO	| PRI | NULL	|	auto_increment |
| ename |	varchar(20)	| YES	|	| NULL	|		|
+	-------	+-------------	+------	+-----	+---------	+----------------	+
*/		
5.5 如何删除自增约束
#给这个字段增加自增约束
#alter table 表名称 modify 字段名 数据类型 auto_increment;alter table 表名称 modify 字段名 数据类型; #去掉auto_increment相当于删除alter table employee modify eid int;
desc employee;	
/*				
+	-------	+-------------	+------	+-----	+---------	+-------	+
| Field |	Type	| Null	| Key | Default	| Extra |
+	-------	+-------------	+------	+-----	+---------	+-------	+
| eid	|	int(11)	| NO	| PRI | NULL	|	|
| ename |	varchar(20)	| YES	|	| NULL	|	|
+	-------	+-------------	+------	+-----	+---------	+-------	+
*/		
5.6 MySQL 8.0新特性—自增变量的持久化

在MySQL 8.0之前,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。 下面通过案例来对比不同的版本中自增变量是否持久化。 在MySQL 5.7版本中,测试步骤如下: 创建的数据表中包含自增主键的id字段,语句如下:

CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT
);

插入4个空值,执行如下:

INSERT INTO test1
VALUES(0),(0),(0),(0);

查询数据表test1中的数据,结果如下:

 SELECT * FROM test1;
/*
+----+| id |+----+|	1 ||	2 ||	3 ||	4 |+----+
*/

删除id为4的记录,语句如下:

DELETE FROM test1 WHERE id = 4;

再次插入一个空值,语句如下:

INSERT INTO test1 VALUES(0);

查询此时数据表test1中的数据,结果如下:

SELECT * FROM test1;
/*
+----+| id |+----+|	1 ||	2 ||	3 ||	5 |+----+*/

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

DELETE FROM test1 where id=5;

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

INSERT INTO test1 values(0);

再次查询数据表test1中的数据,结果如下:

SELECT * FROM test1;
/*
+----+| id |+----+|	1 ||	2 ||	3 ||	4 |+----+
*/

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

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

 SELECT * FROM test1;
/*
+----+| id |+----+|	1 ||	2 ||	3 ||	6 |+----+
*/

从结果可以看出,自增变量已经持久化了。

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

演示代码
#5. 自增长列:AUTO_INCREMENT
# 5.1 在CREATE TABLE时添加
CREATE TABLE test7(
id INT PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(15) 
);
#开发中,一旦主键作用的字段上声明有AUTO_INCREMENT,则我们在添加数据时,就不要给主键
#对应的字段去赋值了。
INSERT INTO test7(last_name)
VALUES('Tom');
INSERT INTO test7(last_name)
VALUES('Tom');SELECT * FROM test7;
/*
+----+-----------+
| id | last_name |
+----+-----------+
|  1 | Tom       |
|  2 | Tom       |
+----+-----------+
*/#当我们向主键(含AUTO_INCREMENT)的字段上添加0 或 null时,实际上会自动的往上添加指定的字段的数值
INSERT INTO test7(id,last_name)
VALUES(0,'Tom');INSERT INTO test7(id,last_name)
VALUES(NULL,'Tom');INSERT INTO test7(id,last_name)
VALUES(10,'Tom');INSERT INTO test7(id,last_name)
VALUES(-10,'Tom');
/*
+-----+-----------+
| id  | last_name |
+-----+-----------+
| -10 | Tom       |
|   1 | Tom       |
|   2 | Tom       |
|   3 | Tom       |
|   4 | Tom       |
|  10 | Tom       |
+-----+-----------+
*/
#开发中,一旦主键作用的字段上声明有AUTO_INCREMENT,则我们在添加数据时,就不要给主键
#对应的字段去赋值了。#5.2 在ALTER TABLE 时添加
CREATE TABLE test8(
id INT PRIMARY KEY ,
last_name VARCHAR(15) 
);DESC test8;ALTER TABLE test8
MODIFY id INT AUTO_INCREMENT;#5.3 在ALTER TABLE 时删除ALTER TABLE test8
MODIFY id INT ;#5.4 MySQL 8.0新特性—自增变量的持久化
#在MySQL 5.7中演示
CREATE TABLE test9(
id INT PRIMARY KEY AUTO_INCREMENT
);INSERT INTO test9
VALUES(0),(0),(0),(0);SELECT * FROM test9;
/*
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+
*/
DELETE FROM test9
WHERE id = 4;INSERT INTO test9
VALUES(0);
/*
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  5 |
+----+
*/
DELETE FROM test9
WHERE id = 5;#重启服务器  net stop mysql57-->net start mysql57SELECT * FROM test9;
/*
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
*/
INSERT INTO test9
VALUES(0);
/*
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+
*/
#-->在5.7中,重启后会接着最大的id值后面增加,即id值是放在内存中维护的
#重启后依据现有id的最大值继续增长#在MySQL 8.0中演示
CREATE TABLE test9(
id INT PRIMARY KEY AUTO_INCREMENT
);INSERT INTO test9
VALUES(0),(0),(0),(0);SELECT * FROM test9;DELETE FROM test9
WHERE id = 4;INSERT INTO test9
VALUES(0);DELETE FROM test9
WHERE id = 5;#重启服务器SELECT * FROM test9;INSERT INTO test9
VALUES(0);
/*
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  6 |
+----+
*/
#-->MySQL 8.0将自增主键的计数器持久化到 重做日志 中。每次计数器发生改变,都会将其写入重做日志
#中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。

6. FOREIGN KEY 约束

6.1 作用

限定某个表的某个字段的引用完整性。

比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。

6.2 关键字

FOREIGN KEY

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

主表(父表):被引用的表,被参考的表
从表(子表):引用别人的表,参考别人的表

例如:员工表的员工所在部门这个字段的值要参考部门表:部门表是主表,员工表是从表。

例如:学生表、课程表、选课表:选课表的学生和课程要分别参考学生表和课程表,学生表和课程表是主表,选课表是从表。

6.4 特点

(1)从表的外键列,必须引用/参考主表的主键或唯一约束的列为什么?因为被依赖/被参考的值必须是唯一的

(2)在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名(例如student_ibfk_1;),也可以指定外键约束名。

(3)创建(CREATE)表时就指定外键约束的话,先创建主表,再创建从表

(4)删表时,先删从表(或先删除外键约束),再删除主表

(5)当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据

(6)在“从表”中指定外键约束,并且一个表可以建立多个外键约束

(7)从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。如果类型不一样,创建子表时,就会出现错误“ERROR 1005 (HY000): Can’t create table’database.tablename’(errno: 150)”。

例如:都是表示部门编号,都是int类型。

(8)当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是外键的约束名。(根据外键查询效率很高)

(9)删除外键约束后,必须 手动 删除对应的索引

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

(3)建表后

一般情况下,表与表的关联都是提前设计好了的,因此,会在创建表的时候就把外键约束定义好。不过,如果需要修改表的设计(比如添加新的字段,增加新的关联关系),但没有预先定义外键约束,那么,就要用修改表的方式来补充定义。

格式:

ALTER TABLE 从表名 ADD [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);

举例:

create table dept(
did int primary key,	#部门编号
dname varchar(50)	#部门名称
);create table emp(
eid int primary key,	#员工编号
ename varchar(5),	#员工姓名
deptid int	#员工所在的部门
);#这两个表创建时,没有指定外键的话,那么创建顺序是随意alter table emp add foreign key (deptid) references dept(did);
1234567891011121314
6.6 演示问题

(1)失败:不是键列

create table dept(
did int ,	#部门编号
dname varchar(50)	#部门名称
);create table emp(
eid int primary key,	#员工编号
ename varchar(5),	#员工姓名
deptid int,	#员工所在的部门
foreign key (deptid) references dept(did)
);
#ERROR 1215 (HY000): Cannot add foreign key constraint	原因是dept的did不是键列

(2)失败:数据类型不一致

create table dept(
did int primary key,	#部门编号
dname varchar(50)	#部门名称
);create table emp(
eid int primary key,	#员工编号
ename varchar(5),	#员工姓名
deptid char,	#员工所在的部门
foreign key (deptid) references dept(did)
);#ERROR 1215 (HY000): Cannot add foreign key constraint 
#原因是从表的deptid字段和主表的did字段的数据类型不一致,并且要它俩的逻辑意义一致

(3)成功,两个表字段名一样

create table dept(
did int primary key,	#部门编号
dname varchar(50)	#部门名称
);create table emp(
eid int primary key,	#员工编号
ename varchar(5),	#员工姓名
did int,	#员工所在的部门
foreign key (did) references dept(did)
#emp表的deptid和和dept表的did的数据类型一致
#意义都是表示部门的编号
#是否重名没问题,因为两个did在不同的表中
);

(4)添加、删除、修改问题

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的数据类型一致,意义都是表示部门的编号
);insert into dept values(1001,'教学部');
insert into dept values(1003, '财务部');#添加从表记录成功,在添加这条记录时,要求部门表有1001部门
insert into emp values(1,'张三',1001); insert into emp values(2,'李四',1005);
#添加从表记录失败ERROR 1452 (23000): Cannot add(添加) or update(修改) a child row: a foreign key constraint fails (`atguigudb`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`deptid`) REFERENCES `dept` (`did`)) 从表emp添加记录失败,因为主表dept没有1005部门select * from dept;
/*
+------	+--------	+
| did	| dname	|
+------	+--------	+
| 1001	| 教学部	|
| 1003	| 财务部	|
+------	+--------	+*/select *	from emp;/*
+	-----	+-------	+--------	+
| eid	| ename |	deptid |
+	-----	+-------	+--------	+
|	1	| 张三	|	1001 |
+	-----	+-------	+--------	+
*/update emp set deptid = 1002 where eid = 1;#修改从表失败
ERROR 1452 (23000): Cannot add(添加) or update(修改) a child row(子表的记录): a foreign key constraint fails(外键约束失败) (`atguigudb`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`deptid`) REFERENCES `dept` (`did`))#部门表did字段现在没有1002的值,所以员工表中不能修改员工所在部门deptid为1002update dept set did = 1002 where did = 1001;#修改主表失败ERROR 1451 (23000): Cannot delete(删除) or update(修改) a parent row(父表的记录): aforeign key constraint fails (`atguigudb`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY(`deptid`) REFERENCES `dept` (`did`)) 
#部门表did的1001字段已经被emp引用了,所以部门表的1001字段就不能修改了。update dept set did = 1002 where did = 1003;
#修改主表成功	因为部门表的1003部门没有被emp表引用,所以可以修改delete from dept where did=1001;#删除主表失败ERROR 1451 (23000): Cannot delete(删除) or update(修改) a parent row(父表记录): a foreign key constraint fails (`atguigudb`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`deptid`) REFERENCES `dept` (`did`)) 
#因为部门表did的1001字段已经被emp引用了,所以部门表的1001字段对应的记录就不能被删除

总结:约束关系是针对双方的

  • 添加了外键约束后,主表的修改和删除数据受约束
  • 添加了外键约束后,从表的添加和修改数据受约束
  • 在从表上建立外键,要求主表必须存在
  • 删除主表时,要求从表从表先删除,或将从表中外键引用该主表的关系先删除
6.7 约束等级
  • Cascade方式 :在父表上update/delete记录时,同步update/delete掉子表的匹配记录
  • Set null方式 :在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null
  • No action方式 :如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
  • Restrict方式 :同no action, 都是立即检查外键约束
  • Set default方式(在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别

如果没有指定等级,就相当于Restrict方式。

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

(1)演示1:on update cascade on delete set null

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);select * from dept;select * from emp;#修改主表成功,从表也跟着修改,修改了主表被引用的字段1002为1004,从表的引用字段就跟着修改为1004了update dept set did = 1004 where did = 1002;
select * from dept;
/*
+------	+--------	+
| did	| dname	|
+------	+--------	+
| 1001	| 教学部 |	
| 1003	| 咨询部 |	
|	1004 | 财务部 | #原来是1002,修改为1004
+------+--------+*/select *	from emp;
/*
+	-----	+-------	+--------	+
| eid |	ename |	deptid |
+	-----	+-------	+--------	+
|	1	|	张三	|	1001	|
|	2	|	李四	|	1001	|
|	3 | 王五 |   1004 | #原来是1002,跟着修改为1004
+-----+-------+--------+*/#删除主表的记录成功,从表对应的字段的值被修改为null
delete from dept where did = 1001;
select * from dept;
/*
+------	+--------	+
| did	| dname	| #记录1001部门被删除了
+------	+--------	+
| 1003	| 咨询部	|
| 1004	| 财务部	|
+------	+--------	+*/select	* from emp;
/*
+	-----+-------	+--------	+
| eid | ename	| deptid |
+	-----+-------	+--------	+
|	1 | 张三 |   NULL | #原来引用1001部门的员工,deptid字段变为null
|	2 | 李四 |   NULL |
|	3 | 王五 | 1004 | */
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263

(2)演示2:on update set null on delete

cascade
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 set null on delete cascade
#把修改操作设置为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);select * from dept;
/*
+	------	+--------	+
| did	| dname	|
+	------	+--------	+
| 1001	| 教学部 |	
| 1002	| 财务部 |	
| 1003	| 咨询部 |	
+	------	+--------	+
*/select *	from emp;/*
+	-----	+-------	+--------	+
| eid |	ename |	deptid |
+	-----	+-------	+--------	+
|	1	|	张三	|	1001	|
|	2	|	李四	|	1001	|
|	3	|	王五	|	1002	|
+	-----	+-------	+--------	+
*/
#修改主表,从表对应的字段设置为nullupdate dept set did = 1004 where did = 1002; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0select *	from dept;
/*
+	------	+--------	+
|	did	|	dname	|
+	------	+--------	+
| 1001	| 教学部 |
|	1003	|	咨询部 |
|	1004 | 财务部 | #原来did是1002
+------+--------+*/select *	from emp;
/*
+	-----	+-------	+--------	+
| eid |	ename |	deptid |
+	-----	+-------	+--------	+
|	1	|	张三	|	1001	|
|	2	|	李四	|	1001	|
|	3 | 王五 | NULL | #原来deptid是1002,因为部门表1002被修改了,1002没有对应的了,就设置为 null
+-----+-------+--------+*/#删除主表的记录成功,主表的1001行被删除了,从表相应的记录也被删除了 delete from dept where did=1001;
Query OK, 1 row affected (0.00 sec)
select * from dept;
/*
+	------	+--------	+
| did		|	dname	| #部门表中1001部门被删除
+	------	+--------	+
| 1003		|	咨询部 |	
| 1004		|	财务部 |	
+	------	+--------	+*/select * from emp;
/*
+	-----	+	-------	+--------	+
| eid	| ename | deptid |#原来1001部门的员工也被删除了
+	-----	+	-------	+--------	+
|	3	| 王五 |	NULL |
+	-----	+	-------	+--------	+
*/
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

(3)演示:on update cascade on delete cascade

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 cascade
#把修改操作设置为级联修改等级,把删除操作也设置为级联删除等级
);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);select * from dept;
/*
+	------	+--------	+
| did	| dname	|
+	------	+--------	+
| 1001	| 教学部 |	
| 1002	| 财务部 |	
| 1003	| 咨询部 |	
+	------	+--------	+
*/select *	from emp;
/*
+	-----	+-------	+--------	+
| eid |	ename |	deptid |
+	-----	+-------	+--------	+
|	1	|	张三	|	1001	|
|	2	|	李四	|	1001	|
|	3	|	王五	|	1002	|
+	-----	+-------	+--------	+
*/#修改主表,从表对应的字段自动修改
update dept set did = 1004 where did = 1002; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0select * from dept;
/*
+------	+--------	+
| did	| dname	|
+------	+--------	+
| 1001	| 教学部 |	
| 1003	| 咨询部 |	
|	1004 | 财务部 | #部门1002修改为1004
+------+--------+*/select *	from emp;
/*
+	-----	+-------	+--------	+
| eid |	ename |	deptid |
+	-----	+-------	+--------	+
|	1	|	张三	|	1001	|
|	2	|	李四	|	1001	|
|	3 | 王五 |   1004 | #级联修改
+-----+-------+--------+*/#删除主表的记录成功,主表的1001行被删除了,从表相应的记录也被删除了 mysql> delete from dept where did=1001;
Query OK, 1 row affected (0.00 sec)select * from dept;
/*
+------	+--------	+
| did	| dname	| #1001部门被删除了
+------	+--------	+
| 1003	| 咨询部 |	
| 1004	| 财务部 |	
+------	+--------	+*/select * from emp;
/*
+	-----	+-------	+--------	+
| eid	| ename | deptid |  #1001部门的员工也被删除了
+	-----	+-------	+--------	+
|	3	| 王五	|	1004 |
+	-----	+-------	+--------	+*/
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
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 索引名;
12345678910

举例:

SELECT * FROM information_schema.table_constraints WHERE table_name = 'emp';alter table emp drop foreign key emp_ibfk_1; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0show index from emp;alter table emp drop index deptid;
Query OK, 0 rows affected (0.01 sec)
Records: 0	Duplicates: 0	Warnings: 0show index from emp;
6.9 开发场景

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

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

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

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

6.10 阿里开发规范

【强制 】不得使用外键与级联,一切外键概念必须在应用层解决。

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

演示代码
#6.foreign key (外键约束)
#限定某个表的某个字段的引用完整性。
#6.1 在CREATE TABLE 时添加#主表和从表;父表和子表#①先创建主表
CREATE TABLE dept1(
dept_id INT,
dept_name VARCHAR(15)
);
#②再创建从表
CREATE TABLE emp1(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(15),
department_id INT,#表级约束
CONSTRAINT fk_emp1_dept_id FOREIGN KEY (department_id) REFERENCES dept1(dept_id));#上述操作报错,因为主表中的dept_id上没有主键约束或唯一性约束。
#③ 添加
ALTER TABLE dept1
ADD PRIMARY KEY (dept_id);DESC dept1;
/*
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| dept_id   | int         | NO   | PRI | NULL    |       |
| dept_name | varchar(15) | YES  |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
*/#④ 再创建从表
CREATE TABLE emp1(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(15),
department_id INT,#表级约束
CONSTRAINT fk_emp1_dept_id FOREIGN KEY (department_id) REFERENCES dept1(dept_id));DESC emp1;
/*
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| emp_id        | int         | NO   | PRI | NULL    | auto_increment |
| emp_name      | varchar(15) | YES  |     | NULL    |                |
| department_id | int         | YES  | MUL | NULL    |                |
+---------------+-------------+------+-----+---------+----------------+
*/
SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'emp1';
/*
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | dbtest13          | PRIMARY         | dbtest13     | emp1       | PRIMARY KEY     | YES      |
| def                | dbtest13          | fk_emp1_dept_id | dbtest13     | emp1       | FOREIGN KEY     | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
*/#6.2 演示外键的效果
#添加失败
INSERT INTO emp1
VALUES(1001,'Tom',10);#
INSERT INTO dept1
VALUES(10,'IT');
#在主表dept1中添加了10号部门以后,我们就可以在从表中添加10号部门的员工
INSERT INTO emp1
VALUES(1001,'Tom',10);#删除失败
DELETE FROM dept1
WHERE dept_id = 10;#更新失败
UPDATE dept1
SET dept_id = 20
WHERE dept_id = 10;#6.3 在ALTER TABLE时添加外键约束
CREATE TABLE dept2(
dept_id INT PRIMARY KEY,
dept_name VARCHAR(15)
);CREATE TABLE emp2(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(15),
department_id INT
);ALTER TABLE emp2
ADD CONSTRAINT fk_emp2_dept_id FOREIGN KEY(department_id) REFERENCES dept2(dept_id);SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'emp2';#6.4 ###  约束等级-- `Cascade方式`:在父表上update/delete记录时,同步update/delete掉子表的匹配记录 -- `Set null方式`:在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null  -- `No action方式`:如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作  -- `Restrict方式`:同no action, 都是立即检查外键约束-- `Set default方式`(在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别#演示:
# on update cascade on delete set null
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);UPDATE dept
SET did = 1004
WHERE did = 1002;DELETE FROM dept
WHERE did = 1004;SELECT * FROM dept;
/*
+------+-----------+
| did  | dname     |
+------+-----------+
| 1001 | 教学部    |
| 1003 | 咨询部    |
+------+-----------+
*/
SELECT * FROM emp;
/*
+-----+--------+--------+
| eid | ename  | deptid |
+-----+--------+--------+
|   1 | 张三   |   1001 |
|   2 | 李四   |   1001 |
|   3 | 王五   |   NULL |
+-----+--------+--------+
*/
#结论:对于外键约束,最好是采用: `ON UPDATE CASCADE ON DELETE RESTRICT` 的方式。#6.5 删除外键约束
#一个表中可以声明有多个外键约束
USE atguigudb;
SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'employees';USE dbtest13;SELECT * FROM information_schema.table_constraints 
WHERE table_name = 'emp1';#删除外键约束ALTER TABLE emp1
DROP FOREIGN KEY fk_emp1_dept_id;#再手动的删除外键约束对应的普通索引
SHOW INDEX FROM emp1;ALTER TABLE emp1
DROP INDEX fk_emp1_dept_id;

7. CHECK 约束

7.1 作用

检查某个字段的值是否符号xx要求,一般指的是值的范围

7.2 关键字

CHECK

7.3 说明:MySQL 5.7 不支持

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

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

create table employee(
eid int primary key,
ename varchar(5),
gender char check ('男' or '女')
);insert into employee values(1,'张三','妖');
select *	from employee;
/*+	-----	+-------	+--------	+
| eid	| ename |	gender |
+	-----	+-------	+--------	+
|	1	| 张三	|	妖	|
+	-----	+-------	+--------	+*/

再举例

CREATE TABLE temp(
id INT AUTO_INCREMENT,
NAME VARCHAR(20),
age INT CHECK(age > 20),
PRIMARY KEY(id)
);

再举例

age tinyint check(age >20) 或 sex char(2) check(sex in(‘男’,’女’))

再举例

CHECK(height>=0 AND height<3)
演示代码
#7. check 约束
#检查某个字段的值是否符号xx要求,一般指的是值的范围
# MySQL5.7 不支持CHECK约束,MySQL8.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);#添加失败
INSERT INTO test10
VALUES(2,'Tom1',1500);SELECT * FROM test10;

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 '' #默认是空字符串
);
desc employee;						
/*+--------	+-------------	+------	+-----	+---------	+-------	+
| Field	|	Type	| Null	| Key	| Default	| Extra |
+--------	+-------------	+------	+-----	+---------	+-------	+
| eid	|	int(11)	|	NO	| PRI	| NULL	|	|
| ename	|	varchar(20) |	NO	|	| NULL	|	|
| gender	|	char(1)	|	YES	|	| 男	|	|
| tel	|	char(11)	| NO	|	|	|	|
+--------	+-------------	+------	+-----	+---------	+-------	+*/insert into employee values(1,'汪飞','男','13700102535'); #成功select *	from employee;	
/*+	-----	+-------	+--------	+-------------	+
| eid	| ename |	gender | tel	|
+	-----	+-------	+--------	+-------------	+
|	1	| 汪飞	|	男	| 13700102535 |	
+	-----	+-------	+--------	+-------------	+*/insert into employee(eid,ename) values(2,'天琪'); #成功select *	from employee;	
/*+	-----	+-------	+--------	+-------------	+
| eid |	ename |	gender | tel	|
+	-----	+-------	+--------	+-------------	+
|	1	|	汪飞	|	男	| 13700102535 |
|	2	|	天琪	|	男	|	|
+	-----	+-------	+--------	+-------------+*/insert into employee(eid,ename) values(3,'二虎'); 
#ERROR 1062 (23000): Duplicate entry '' for key 'tel'#如果tel有唯一性约束的话会报错,如果tel没有唯一性约束,可以添加成功

再举例:

CREATE TABLE myemp(
id INT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(15),
salary DOUBLE(10,2) DEFAULT 2000
);

(2)建表后

alter table 表名称 modify 字段名 数据类型 default 默认值;
#如果这个字段原来有非空约束,你还保留非空约束
#那么在加默认值约束时,还得保留非空约束,否则非空约束就被删除了#同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默认值约束,否则就删除了alter table 表名称 modify 字段名 数据类型 default 默认值 not null;create table employee(
eid int primary key,
ename varchar(20),
gender char,
tel char(11) not null
);
desc employee;						
/*+--------	+-------------	+------	+-----	+---------	+-------	+
| Field	| Type	| Null | Key |	Default	| Extra |
+--------	+-------------	+------	+-----	+---------	+-------	+
| eid	| int(11)	| NO	| PRI |	NULL	|	|
| ename	| varchar(20) | YES	|	|	NULL	|	|
| gender	| char(1)	| YES	|	|	NULL	|	|
| tel	| char(11)	| NO	|	|	NULL	|	|
+--------	+-------------	+------	+-----	+---------	+-------	+*/alter table employee modify gender char default '男';#给gender字段增加默认值约束 alter table employee modify tel char(11) default '';#给tel字段增加默认值约束desc employee;						
/*+--------	+-------------	+------	+-----	+---------	+-------	+
| Field	| Type	| Null | Key |	Default	| Extra |
+--------	+-------------	+------	+-----	+---------	+-------	+
| eid	| int(11)	| NO	| PRI |	NULL	|	|
| ename	| varchar(20) | YES	|	|	NULL	|	|
| gender	| char(1)	| YES	|	|	男	|	|
| tel	| char(11)	| YES	|	|		|	|
+--------	+-------------	+------	+-----	+---------	+-------	+*/alter table employee modify tel char(11) default ''	not null;
#给tel字段增加默认值约束,并保留非空约束desc employee;						
/*+--------	+-------------	+------	+-----	+---------	+-------	+
| Field	|	Type	| Null	| Key	| Default	| Extra |
+--------	+-------------	+------	+-----	+---------	+-------	+
| eid	|	int(11)	|	NO	| PRI	| NULL	|	|
| ename	|	varchar(20) |	YES	|	| NULL	|	|
| gender	|	char(1)	|	YES	|	| 男	|	|
| tel	|	char(11)	| NO	|	|	|	|
+--------	+-------------	+------	+-----	+---------	+-------	+*/
8.4 如何删除默认值约束
alter table 表名称 modify 字段名 数据类型 ;
#删除默认值约束,也不保留非空约束alter table 表名称 modify 字段名 数据类型	not null; 
#删除默认值约束,保留非空约束alter table employee modify gender char;#删除gender字段默认值约束,如果有非空约束,也一并删除 alter table employee modify tel char(11) not null;#删除tel字段默认值约束,保留非空约束desc employee;						
/*+--------	+-------------	+------	+-----	+---------	+-------	+
| Field	| Type	| Null | Key |	Default	| Extra |
+--------	+-------------	+------	+-----	+---------	+-------	+
| eid	| int(11)	| NO	| PRI |	NULL	|	|
| ename	| varchar(20) | YES	|	|	NULL	|	|
| gender	| char(1)	| YES	|	|	NULL	|	|
| tel	| char(11)	| NO	|	|	NULL	|	|
+--------	+-------------	+------	+-----	+---------	+-------	+*/
演示代码
#8.DEFAULT约束
#给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,
#如果此字段没有显式赋值,则赋值为默认值。
#8.1 在CREATE TABLE添加约束
CREATE TABLE test11(
id INT,
last_name VARCHAR(15),
salary DECIMAL(10,2) DEFAULT 2000
);DESC test11;INSERT INTO test11(id,last_name,salary)
VALUES(1,'Tom',3000);INSERT INTO test11(id,last_name)
VALUES(2,'Tom1');SELECT * 
FROM test11;#8.2 在ALTER TABLE添加约束
CREATE TABLE test12(
id INT,
last_name VARCHAR(15),
salary DECIMAL(10,2)
);DESC test12;ALTER TABLE test12
MODIFY salary DECIMAL(8,2) DEFAULT 2500;#8.3 在ALTER TABLE删除约束
ALTER TABLE test12
MODIFY salary DECIMAL(8,2);SHOW CREATE TABLE test12;

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支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的

课后练习

#第13章_约束的课后练习
#已经存在数据库test04_emp,两张表emp2和dept2
#练习1:
CREATE DATABASE test04_emp;USE test04_emp;CREATE TABLE emp2(
id INT,
emp_name VARCHAR(15)
);CREATE TABLE dept2(
id INT,
dept_name VARCHAR(15)
);#1.向表emp2的id列中添加PRIMARY KEY约束ALTER TABLE emp2
ADD CONSTRAINT pk_emp2_id PRIMARY KEY(id);#2.向表dept2的id列中添加PRIMARY KEY约束ALTER TABLE dept2
ADD PRIMARY KEY(id);#3.向表emp2中添加列dept_id,并在其中定义FOREIGN KEY约束,与之相关联的列是dept2表中的id列。ALTER TABLE emp2
ADD dept_id INT;DESC emp2;
/*
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int         | NO   | PRI | NULL    |       |
| emp_name | varchar(15) | YES  |     | NULL    |       |
| dept_id  | int         | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
*/ALTER TABLE emp2
ADD CONSTRAINT fk_emp2_deptid FOREIGN KEY(dept_id) REFERENCES dept2(id);#练习2:
#承接《第11章_数据处理之增删改》的综合案例。
USE test01_library;DESC books;
/*
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int          | YES  |     | NULL    |       |
| name    | varchar(50)  | YES  |     | NULL    |       |
| authors | varchar(100) | YES  |     | NULL    |       |
| price   | float        | YES  |     | NULL    |       |
| pubdate | year         | YES  |     | NULL    |       |
| note    | varchar(100) | YES  |     | NULL    |       |
| num     | int          | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
*/
#根据题目要求给books表中的字段添加约束
#方式1:
ALTER TABLE books
ADD PRIMARY KEY (id);ALTER TABLE books
MODIFY id INT AUTO_INCREMENT;
#方式2:
ALTER TABLE books
MODIFY id INT PRIMARY KEY AUTO_INCREMENT;#针对于非id字段的操作
ALTER TABLE books
MODIFY NAME VARCHAR(50) NOT NULL;ALTER TABLE books
MODIFY AUTHORS VARCHAR(100) NOT NULL;ALTER TABLE books
MODIFY price FLOAT NOT NULL;ALTER TABLE books
MODIFY pubdate YEAR NOT NULL;ALTER TABLE books
MODIFY num INT NOT NULL;#练习3:
#1. 创建数据库test04_company
CREATE DATABASE IF NOT EXISTS test04_company CHARACTER SET 'utf8';USE test04_company;#2. 按照下表给出的表结构在test04_company数据库中创建两个数据表offices和employeesCREATE TABLE IF NOT EXISTS offices(
officeCode INT(10) PRIMARY KEY ,
city VARCHAR(50) NOT NULL,
address VARCHAR(50) ,
country VARCHAR(50) NOT NULL,
postalCode VARCHAR(15),
CONSTRAINT uk_off_poscode UNIQUE(postalCode));DESC offices;CREATE TABLE employees(
employeeNumber INT PRIMARY KEY AUTO_INCREMENT,
lastName VARCHAR(50) NOT NULL,
firstName VARCHAR(50) NOT NULL,
mobile VARCHAR(25) UNIQUE,
officeCode INT(10) NOT NULL,
jobTitle VARCHAR(50) NOT NULL,
birth DATETIME NOT NULL,
note VARCHAR(255),
sex VARCHAR(5),
CONSTRAINT fk_emp_offcode FOREIGN KEY (officeCode) REFERENCES offices(officeCode));DESC employees;#3. 将表employees的mobile字段修改到officeCode字段后面
ALTER TABLE employees
MODIFY mobile VARCHAR(25) AFTER officeCode;#4. 将表employees的birth字段改名为employee_birth
ALTER TABLE employees
CHANGE birth employee_birth DATETIME;#5. 修改sex字段,数据类型为CHAR(1),非空约束
ALTER TABLE employees
MODIFY sex CHAR(1) NOT NULL;#6. 删除字段note
ALTER TABLE employees
DROP COLUMN note;#7. 增加字段名favoriate_activity,数据类型为VARCHAR(100)
ALTER TABLE employees
ADD favoriate_activity VARCHAR(100);#8. 将表employees名称修改为employees_info
RENAME TABLE employees
TO employees_info;#错误:Table 'test04_company.employees' doesn't exist
DESC employees;DESC employees_info;

相关文章:

MySQL | 尚硅谷 | 第13章_约束

MySQL笔记&#xff1a;第13章_约束 文章目录 MySQL笔记&#xff1a;第13章_约束第13章_约束 1. 约束(constraint)概述1.1 为什么需要约束1.2 什么是约束1.3 约束的分类演示代码 2. 非空约束2.1 作用2.2 关键字2.3 特点2.4 添加非空约束2.5 删除非空约束演示代码 3. 唯一性约束3…...

【Ubuntu】Ubuntu的Desktop(学习/用户使用)和Bit版本(工作)

这篇文章似乎没什么必要写&#xff0c;但想了想还是决定记录一下&#xff0c;也许对新手入坑Ubuntu会有帮助&#xff0c; 事实上也很简单&#xff0c;一个是桌面版本&#xff0c;另一个是字符界面版本。 桌面版&#xff1a;拥有图形桌面 字符界面&#xff0c;易上手&#xff…...

面试之MySQL自增ID耗尽问题的解决方案详解

自增ID耗尽问题的解决方案详解 目录 引言切换到BIGINT分表分库UUID雪花算法&#xff08;Snowflake&#xff09;回收已删除的ID其他策略策略选择和实施总结 引言 在现代数据库应用中&#xff0c;自增ID作为主键被广泛使用。随着数据量的不断增长&#xff0c;自增ID耗尽问题逐…...

数据结构第一弹-平衡树

大家好&#xff0c;今天和大家一起分享一下数据结构中的平衡树~ 平衡树是一种特别重要的数据结构&#xff0c;它通过维持树的高度来保证操作的效率&#xff0c;从而在众多数据结构中脱颖而出。我们今天深入探讨平衡树的概念、种类、工作原理以及应用实例。 1. 平衡树简介 平衡…...

k8s二进制部署集群报错

k8s二进制部署的集群 添加node节点之后 部署服务之后出现报错 在该节点上telnet 172.30.0.1 443也不通 其他正常节点telnet是通的 解决办法&#xff1a; 修改kube-proxy的服务配置 systemctl daemon-reload systemctl restart kube-proxy再次telnet通了...

深入了解架构中常见的4种缓存模式及其实现

4种缓存模式 随着应用程序的复杂性日益增加&#xff0c;缓存管理变得至关重要。缓存不仅能有效减轻数据库负载&#xff0c;还能显著提升数据访问速度。选择合适的缓存模式能够在不同的业务场景下发挥出最佳效果。 本文将详细介绍四种常见的缓存模式&#xff1a;Cache-Aside (…...

python pyqt5 优秀的开源项目

目录 1. Qutebrowser 2. Anki 3. Calibre 4. Spyder 5. Leo Editor 6. Trelby 7. Eric IDE 8. Fman 9. Gramps 10. OpenShot 使用 PyQt5 开发的优秀开源项目涵盖了各种应用领域,包括桌面应用、开发工具、教育软件等。以下是一些值得关注的 PyQt5 开源项目: 1. Qut…...

【C++】关系操作符的全面解析与高级应用

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;关系操作符1.关系操作符的分类与语义2.关系操作符的连用问题3.浮点数比较的精度问题问题示例解决方案 &#x1f4af;总结核心要点 &#x1f4af;小结 &#x1f4af;前言 在…...

Git进行版本控制的VS项目中特定配置

在使用Git进行版本控制的VS&#xff08;Visual Studio&#xff09;项目中&#xff0c;通常有一些文件和目录是不需要提交到仓库中的。这些文件通常是编译生成的输出、临时文件、用户特定配置等。为了告诉Git忽略这些文件&#xff0c;你应该编辑或创建一个.gitignore文件&#x…...

Linux Ubuntu 安装配置RabbitMQ,springboot使用RabbitMQ

rabbit-Ubuntu 一篇文章学会RabbitMQ 在Ubuntu上查看RabbitMQ状态可以通过多种方式进行&#xff0c;包括使用命令行工具和Web管理界面。以下是一些常用的方法&#xff1a; 1-使用systemctl命令&#xff1a; sudo systemctl start rabbitmq-server sudo systemctl status ra…...

MongoDB数据建模小案例

MongoDB数据建模小案例 朋友圈评论内容管理 需求 社交类的APP需求,一般都会引入“朋友圈”功能,这个产品特性有一个非常重要的功能就是评论体系。 先整理下需求: 这个APP希望点赞和评论信息都要包含头像信息: 点赞列表,点赞用户的昵称,头像;评论列表,评论用户的昵称…...

基于MATLAB野外观测站生态气象数据处理分析实践应用

1.本课程基于MATLAB语言 2.以实践案例为主&#xff0c;提供所有代码 3.原理与操作结合 4.布置作业&#xff0c;答疑与拓展 示意图&#xff1a; 以野外观测站高频时序生态气象数据为例&#xff0c;基于MATLAB开展上机操作&#xff1a; 1.不同生态气象要素文件的数据读写与批处理…...

《三角洲行动》游戏安全组件运行时发生异常1-0-0,是什么原因?以及要如何解决?

《三角洲行动》游戏安全组件异常1-0-0深度探讨 今天你们安全撤离了吗&#xff1f;在《三角洲行动》这款经典射击游戏里&#xff0c;游戏安全组件运行时发生异常1-0-0的原因及解决方案&#xff0c;并借此机会分享一些有关文件丢失、文件损坏和系统报错等问题的通用解决策略。希…...

VAS1260Q奇力LED驱动芯片DCDC降压恒流可替代Diodes8860

VAS1260Q是一款专为车规级LED照明设计的连续模式电感降压驱动器&#xff0c;能够高效地驱动单个或多个串联LED。它集成了高端输出电流检测电路&#xff0c;并通过外部电阻设置标称平均输出电流&#xff0c;具有高可靠性和宽广的应用场景。 核心技术参数 1. 输入电压范围…...

leetcode-88.合并两个有序数组(易理解)

双指针 为了合并两个已排序的数组 nums1 和 nums2&#xff0c;并将结果存储在 nums1 中&#xff0c;我们可以采用双指针的方式从后向前进行合并。这种方法的好处是可以避免在nums1中移动元素&#xff0c;从而提高效率。 算法步骤 初始化三个指针&#xff1a; p1 指向 nums1 的…...

github操作学习笔记

git开源的分布式版本控制系统&#xff1a; 每次修改文件提交后&#xff0c;都会自动创建一个项目版本 查看git版本看有没有安装成功&#xff1a;git --version 把默认编辑器设置成vim&#xff1a;git config --global core.editor "vim" 1、设置昵称和邮箱&#xff…...

基于Hadoop大数据音乐推荐系统的设计与实现

摘 要 各种主流的音乐平台都为用户提供了的大量的音乐&#xff0c;让他们时刻都能沉浸在音乐的海洋之中。然而&#xff0c;过多的音乐往往使用户眼花缭乱&#xff0c;很难发现他们真正所需要的。一套优秀的推荐系统&#xff0c;可以很好地解决这个问题&#xff0c;既能帮助用户…...

【Linux】冯诺依曼体系结构

目录 一、冯诺依曼体系结构二、冯诺依曼体系结构的基本组成三、关于冯诺依曼体系结构的一些问题结尾 一、冯诺依曼体系结构 冯诺依曼体系结构&#xff0c;也称为普林斯顿结构&#xff0c;是现代计算机设计的基础框架。这一体系结构由数学家冯诺依曼在20世纪40年代提出&#xf…...

2025计算机毕设选题推荐【小程序方向】【基础功能+创新点设计】

✅博主介绍&#xff1a;CSDN毕设辅导博主、CSDN认证 Java领域优质创作者 ✅技术范围&#xff1a;主要包括Java、Vue、Python、爬虫、小程序、安卓app、大数据、机器学习等设计与开发。 ✅主要内容&#xff1a;免费功能设计、开题报告、任务书、功能实现、代码编写、论文编写和…...

CSS系列(3)-- 定位与文档流详解

前端技术探索系列&#xff1a;CSS 定位与文档流详解 &#x1f4cd; 致读者&#xff1a;掌握页面布局的精髓 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS 定位与文档流&#xff0c;这是掌握页面布局的关键所在。通过本文&#xff0c;你将全面理解各种定位…...

【书生大模型实战营】Linux 基础知识-L0G1000

前言&#xff1a;书生大模型实战营是上海人工智能实验室开展的大模型系列实践活动&#xff0c;提供免费算力平台&#xff0c;学员通过闯关式任务&#xff0c;可获得免费算力和存储&#xff0c;助力项目实践。本期是第4期&#xff0c;时间从十一月份开始&#xff0c;持续到十二月…...

小程序IOS安全区域优化:safe-area-inset-bottom

ios下边有一个小黑线&#xff0c;位于底部的元素会被黑线阻挡 safe-area-inset-bottom 一 用法及作用&#xff1a; IOS全面屏底部有小黑线&#xff0c;位于底部的元素会被黑线阻挡&#xff0c;可以使用以下样式&#xff1a; .model{padding-bottom: constant(safe-area-ins…...

STM32-C语言基础知识

C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程&#xff1a;先清0&#xff0c;再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句&#xff0c;如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…...

深度和法线纹理

屏幕后期处理效果的基本原理就是当游戏画面渲染完毕后通过获取到该画面的信息进行额外的效果处理 之前的边缘检测、高斯模糊、Bloom、运动模糊等效果都是基于获取当前屏幕图像中的像素信息进行后期处理的 如果仅仅根据像素信息来进行一些效果处理&#xff0c;存在以下问题&…...

21天掌握javaweb-->第11天:前端性能优化与响应式设计

前端性能优化与响应式设计 1. 前端性能优化技巧 1.1 代码分割&#xff08;Code Splitting&#xff09; 代码分割是一种将代码拆分成多个较小的包&#xff0c;并在需要时按需加载的技术&#xff0c;这有助于减少初始加载时间&#xff0c;并提高应用程序的响应速度。 实现方法…...

java+ssm+mysql校园物品租赁网

项目介绍&#xff1a; 使用javassmmysql开发的校园物品租赁网&#xff0c;系统包含管理员、用户角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;用户管理&#xff1b;物品管理&#xff08;物品种类、物品信息、评论信息&#xff09;&#xff1b;订单管理&#xff1…...

C#常见错误—空对象错误

System.NullReferenceException&#xff1a;未将对象引用设置到对象的实例 在C#编程中&#xff0c;System.NullReferenceException是一个常见的运行时异常&#xff0c;其错误信息“未将对象引用设置到对象的实例”意味着代码试图访问一个未被初始化或已被设置为null的对象的成…...

GPT系列模型简要概述

GPT-1&#xff1a;&#xff08;0.117B参数量&#xff0c;0.8B words预训练数据) 动机&#xff1a; 在RNN和Transformer之间&#xff0c;选择了后者。 和《All your need is Attention》翻译模型的Encoder-Decoder架构相比&#xff0c;只保留Decoder&#xff0c;因此去掉了Cross…...

关于睡懒觉

我们经常听到一个词&#xff1a;睡懒觉。 我认为&#xff0c;睡懒觉这个词&#xff0c;是错误的。 人&#xff0c;是需要睡眠的&#xff0c;睡不够&#xff0c;就不会醒。睡够了&#xff0c;自然会醒&#xff0c;也不想继续睡。不信你试试&#xff0c;睡够了&#xff0c;你…...

Spring Data JPA 入门

文章目录 前言、Spring Data JPA 是什么&#xff1f;1、背景2、优势3、Spring Data JPA 和 MyBatis-Plus 对比4、Spring Data JPA 与 JPA 的关系是什么&#xff1f; 一、准备1、依赖引入Spring Boot 框架依赖引入&#xff1a;非 Spring Boot 框架依赖引入&#xff1a; 2、定义实…...

操作系统用户界面

实验目的&#xff1a; LINUX操作系统提供了图形用户界面和命令行界面&#xff0c;本实验主要熟悉命令行界面&#xff0c;为后续的实验编程做准备。 二、实验内容&#xff1a; 写出每个命令的功能及格式 1、有关目录和文件操作的命令 1.1cat 功能&#xff1a; 1.一次显示整…...

区块链dapp 开发详解(VUE3.0)

1、安装metamask 插件。 2、使用封装的工具包: wagmi . 3、 wagmi 操作手册地址:connect | Wagmi 4、注意事项&#xff1a; 因为最初是react 版本&#xff0c;所以在VUE版的官方文档有很多地方在 import 用的是 wagmi,需要改为 wagmi/vue 。 连接成功后打印的内容如下&…...

BTC密码学原理

文章目录 比特币的密码学基础哈希函数&#xff08;Hash Function&#xff09;非对称加密&#xff08;Asymmetric Cryptography&#xff09;数字签名&#xff08;Digital Signature&#xff09; 工作量证明&#xff08;Proof of Work&#xff09;区块链技术的密码学保障区块链的…...

【NLP 9、实践 ① 五维随机向量交叉熵多分类】

目录 五维向量交叉熵多分类 规律&#xff1a; 实现&#xff1a; 1.设计模型 2.生成数据集 3.模型测试 4.模型训练 5.对训练的模型进行验证 调用模型 你的平静&#xff0c;是你最强的力量 —— 24.12.6 五维向量交叉熵多分类 规律&#xff1a; x是一个五维(索引)向量&#xff…...

Linux -文件系统的备份

本文为Ubuntu Linux操作系统- 第九弹~~ 今天接着上文的内容&#xff0c;讲Linux磁盘存储管理最后一部分内容~ 上期回顾&#xff1a;Linux 图形界面工具管理磁盘分区和文件系统 &#x1f60e;黑犀铠甲合体&#xff0c;流星枪之狂瀑扎帖&#xff0c;碎魔伏暴&#xff0c;灭于狂瀑…...

【Linux基础五】Linux开发工具—上(apt和vim)

【Linux基础五】Linux开发工具—上&#xff08;apt和vim&#xff09; 1.apt包管理工具2.Linux中的编辑器vim2.1命令模式2.2插入模式2.3底行模式2.4替换模式2.5视图模式2.6多线程操作2.7配置vim 1.apt包管理工具 在 Linux 系统中&#xff0c;软件包管理工具是用户安装、更新和管…...

力扣--LCR 134.Pow(x,n)

题目 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000 示例 2&#xff1a; 输入&#xff1a;x 2.10000, n 3 输出&#xff1a;9.2610…...

java抽奖系统(一)2.0

1. 项⽬介绍 1.1 背景 随着数字营销的兴起&#xff0c;企业越来越重视通过在线活动来吸引和留住客⼾。抽奖活动作为⼀种有效的营 销⼿段&#xff0c;能够显著提升⽤⼾参与度和品牌曝光率。于是我们就开发了以抽奖活动作为背景的Spring Boot项⽬&#xff0c;通过这个项⽬提供⼀…...

读取电视剧MP4视频的每一帧,检测出现的每一个人脸并保存

检测效果还不错,就是追踪有点难做 import cv2 import mediapipe as mp import os from collections import defaultdict# pip install msvc-runtime# 初始化OpenCV的MultiTracker # multi_tracker = cv2.MultiTracker_create() # multi_tracker = cv2.legacy.MultiTracker_cre…...

【MySQL 进阶之路】事务并发情况分析

MySQL事务并发控制分析笔记 在数据库系统中&#xff0c;事务并发控制至关重要&#xff0c;能够确保多个事务并发执行时的数据一致性、隔离性和正确性。MySQL通过不同的锁机制控制并发操作&#xff0c;以确保事务的隔离性。以下是对事务A和事务B并发行为的详细分析&#xff0c;…...

基于SSM的线上考试系统的设计与实现(计算机毕业设计)+万字说明文档

系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可 操作系统…...

redis击穿,穿透,雪崩以及解决方案

目录 击穿 解决方案一 解决方案二 穿透 解决方案 雪崩 解决方案 击穿 指的是单个key在缓存中查不到&#xff0c;去数据库查询&#xff0c;这样如果并发不大或者数据库数据量不大的话是没有什么问题的。 如果数据库数据量大并且是高并发的情况下那么就可能会造成数据库压…...

Flask返回中文Unicode编码(乱码)解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

EasyExcel改名为FastExce做了那些改变呢

回到&#xff1a;github原作者地址&#xff1a;https://github.com/CodePhiliaX/fastexcel 中文 |English | 什么是 FastExcel FastExcel 是由原 EasyExcel 作者创建的新项目。2023 年我已从阿里离职&#xff0c;近期阿里宣布停止更新 EasyExcel&#xff0c;作者他本人决定继…...

数据结构之初始二叉树(1)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 树型结构 树的概念 与树的有关概念 树的表示形式 树的应用 二叉树 概念 两种特殊的…...

利用Python爬虫按图搜索淘宝商品(拍立淘)

在当今数字化时代&#xff0c;能够通过图片搜索商品的功能&#xff08;如淘宝的“拍立淘”&#xff09;为用户提供了极大的便利。本文将详细介绍如何利用Python爬虫技术实现按图搜索淘宝商品&#xff0c;并提供相应的代码示例。 1. 拍立淘功能简介 “拍立淘”是淘宝提供的一项…...

微信小程序中使用miniprogram-sm-crypto实现SM4加密攻略

在微信小程序开发过程中&#xff0c;数据安全至关重要。本文将为大家介绍如何在微信小程序中使用miniprogram-sm-crypto插件进行SM4加密&#xff0c;确保数据传输的安全性。 一、SM4加密简介 SM4是一种对称加密算法&#xff0c;由国家密码管理局发布&#xff0c;适用于商密领…...

基于注解的方式实现分布式锁的AOP功能

使用场景&#xff1a; 在分布式项目中&#xff0c;涉及到事务&#xff0c;且会操作多张表&#xff0c;那么涉及到并发场景&#xff0c;应当避免同一时间有多个用户并发操作同一份数据&#xff0c;例如&#xff1a;商品秒杀。 解决方案&#xff1a; 使用Around注解实现在方法…...

22. 五子棋小游戏

文章目录 概要整体架构流程技术名词解释技术细节小结 1. 概要 &#x1f50a; JackQiao 对 米粒 说&#xff1a;“今天咱们玩个五子棋小游戏&#xff0c;电脑与你轮流在一个 nn 的网格上放置棋子&#xff08;X 或 O&#xff09;&#xff0c;网格由你输入的正整数n决定&#xff0…...

import是如何“占领满屏“

import是如何“占领满屏“的&#xff1f; 《拒绝使用模块重导&#xff08;Re-export&#xff09;》 模块重导是一种通用的技术。在腾讯、字节、阿里等各大厂的组件库中都有大量使用。 如&#xff1a;字节的arco-design组件库中的组件&#xff1a;github.com/arco-design… …...