MySQL笔记

  1. 基本概念
    DBMS 和 RDBMS
    发展历史
    关系型数据库和非关系型数据库

2.ER模型与表记录的4种关系:

表与表之间的数据记录有关系(relationship)。现实世界中的各种实体以及实体之间的各种联系均用

关系模型来表示。

一对一: 这种通常将所有数据放在一张表中

一对多: 一个用户有多个订单(客户和订单是一对多的关系)、一个部门多个员工

多对多: 要表示多对多关系,必须创建第三个表,该表通常称为联接表,它将多对多关系划分为两个一对多关

系。将这两个表的主键都插入到第三个表中。

例子: 学生与课程就是多对多: 一个学生可以选多门课, 一门课可以被多个学生选择

选课信息表作为中间表,记录了每个学生的选课信息

订单与产品是多对多: 一个订单可以有多个产品,每个产品可以出现在多个订单中

订单明细表就是中间表

自我引用: 自己引用自己

例子: 员工表中,有员工id,Managerid,一个人他可能即是员工又是管理者,

Managerid是103的记录和员工id是103的记录,之间就是自我引用

  1. 基本的Select语句

1)SQL语句分类:

  1. DDL(Data Definition Languages、数据定义语言),这些语句定义了不同的数据库、表、视图、索
    引等数据库对象,还可以用来创建、删除、修改数据库和数据表的结构。 --> 对库和表结构的的定义、增删改
    主要的语句关键字包括CREATE 、DROP 、ALTER 等。
  2. DML(Data Manipulation Language、数据操作语言),用于添加、删除、更新和查询数据库记
    录,并检查数据完整性。
    主要的语句关键字包括INSERT 、DELETE 、UPDATE 、SELECT 等。
    SELECT是SQL语言的基础,最为重要。 --> 对数据的增删改查
  3. DCL(Data Control Language、数据控制语言),用于定义数据库、表、字段、用户的访问权限和
    安全级别。

因为查询语句使用的非常的频繁,所以很多人把查询语句单拎出来一类:DQL(数据查询语言)。

还有单独将COMMIT 、ROLLBACK 取出来称为TCL (Transaction Control Language,事务控制语

言)。

  1. 列取别名:
    as:全称:alias(别名),可以省略

列的别名可以使用一对""引起来,不要使用''。

SELECT employee_id emp_id,last_name AS lname,department_id "部门id",salary * 12 AS "annual sal"

FROM employees;

  1. 去除重复行
    DISTINCT
    SELECT DISTINCT department_id
    FROM employees;

两点:

DISTINCT放到所有列名的最前面.

ISTINCT 其实是对后面所有列名的组合进行去重.

  1. 空值参与运算
    所有运算符或列值遇到null值,运算的结果都为null

5)使用WHERE过滤数据

#练习:查询90号部门的员工信息

SELECT *

FROM employees

#过滤条件,声明在FROM结构的后面

WHERE department_id = 90;

  1. 运算符
  2. 算术运算符: + - * / div % mod
  3. 比较运算符
    2.1 = <=> <> != < <= > >=
    2.2 IS NULL \ IS NOT NULL \ ISNULL
    2.3 BETWEEN 条件下界1 AND 条件上界2 (查询条件1和条件2范围内的数据,包含边界)
    2.4 LIKE 模糊查询
    "%":匹配0个或多个字符。
    "_":只能匹配一个字符。

#练习:查询last_name中包含字符'a'的员工信息

SELECT last_name

FROM employees

WHERE last_name LIKE '%a%';

_ :代表一个不确定的字符

#练习:查询第3个字符是'a'的员工信息

SELECT last_name

FROM employees

WHERE last_name LIKE '__a%';

2.5 REGEXP :正则表达式

(1)'^'匹配以该字符后面的字符开头的字符串。 ^a 匹配以a开头的字符串

(2)''匹配以该字符前面的字符结尾的字符串。 a 匹配以a结尾的字符串

2.6 逻辑运算符: OR || AND && NOT ! XOR

2.7 位运算符: & | ^ ~ >> <<

  1. 排序与分页
  1. 使用 ORDER BY 对查询到的数据进行排序操作。
    升序:ASC (ascend)
    降序:DESC (descend)

练习:按照salary从高到低的顺序显示员工信息

SELECT employee_id,last_name,salary

FROM employees

ORDER BY salary DESC; // 默认按照升序排列

使用多列进行排序:

#练习:显示员工信息,按照department_id的降序排列,salary的升序排列

SELECT employee_id,salary,department_id

FROM employees

ORDER BY department_id DESC,salary ASC;

A.可以使用不在SELECT列表中的列排序。

B.在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第

一列数据中所有值都是唯一的,将不再对第二列进行排序。

2)LIMIT 用于分页

语法:

LIMIT [从哪开始返回,] 返回多少行

MySQL 8.0中的语法:

LIMIT 返回多少行 OFFSET 从哪开始返回

需求1:每页显示20条记录,此时显示第1页

SELECT employee_id,last_name

FROM employees

LIMIT 0,20;

#需求:每页显示pageSize条记录,此时显示第pageNo页:

#公式:LIMIT (pageNo-1) * pageSize,pageSize;

注意:

ORDER BY 和 LIMIT应该位于在整个SELECT语句的最后.

LIMIT 应该在ORDER BY 的后面

  1. 多表查询

  2. 单行函数

    这章可以跳过,讲的是MySQL里面提供的一些函数,用的时候再查。每个函数

    PDF里面有详细的介绍

函数分类: 单行函数与多行函数

单行函数:只对一行进行变换, 每行返回一个结果

多行函数:对多行进行变换, 整体返回一个结果

单行函数有这些:

1)基本函数

求绝对值、随机值等

2)角度与弧度互换函数

3)三角函数

4)指数与对数

5)进制间的转换

6)字符串函数:

LENGTH(s) 返回字符串s的字节数,和字符集有关

CONCAT(s1,s2,...,sn) 连接s1,s2,...,sn为一个字符串

还有REPLACE、INSERT、FIND等

7)日期和时间函数

包括获取当前时间、时间转换、格式化、时间之间的计算等

8)流程控制函数

IF、IFNULL、CASE...WHEN等

IF(value,value1,value2) 如果value的值为TRUE,返回value1,否则返回value2

IFNULL(value1, value2) 如果value1不为NULL,返回value1,否则返回value2

CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2... [ELSE resultn] END -> 相当于Java的if...else if...else...

例子:

SELECT last_name,salary,CASE WHEN salary >= 15000 THEN '白骨精'

WHEN salary >= 10000 THEN '潜力股'

WHEN salary >= 8000 THEN '小屌丝'

ELSE '草根' END "details",department_id

CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN值1 ... [ELSE 值n] END -> 相当于Java的switch...case...

/*

练习1

查询部门号为 10,20, 30 的员工信息,

若部门号为 10, 则打印其工资的 1.1 倍,

20 号部门, 则打印其工资的 1.2 倍,

30 号部门,打印其工资的 1.3 倍数,

其他部门,打印其工资的 1.4 倍数

*/

SELECT employee_id,last_name,department_id,salary,CASE department_id WHEN 10 THEN salary * 1.1

WHEN 20 THEN salary * 1.2

WHEN 30 THEN salary * 1.3

ELSE salary * 1.4 END "details"

FROM employees;

9)加密与解密函数

密码加解密、md5等

  1. MySQL信息函数

获取当前MySQL的一些信息,例如版本、连接数等

  1. 多行函数(聚合函数、组函数、聚集函数)
    聚合函数作用于一组数据,并对一组数据返回一个值。

常见的几个聚合函数

AVG、SUM、MAX、MIN、COUNT

1)可以对数值型数据使用AVG 和 SUM 函数。

例子: 对薪水求平均值和求和

SELECT AVG(salary),SUM(salary),AVG(salary) * 107

FROM employees;

2)可以对任意数据类型的数据使用 MIN 和 MAX 函数。

例子: 对薪水求最大、最小值

SELECT MAX(salary),MIN(salary)

FROM employees;

例子: 对last_name、hire_date求最大最小值,hire_date是日期类型、last_name是字符串

SELECT MAX(last_name),MIN(last_name),MAX(hire_date),MIN(hire_date)

FROM employees;

3)COUNT: 计算指定字段在查询结构中出现的个数(不包含NULL值的,如果指定的字段是NULL,则这一行不会被统计)

例子:

SELECT COUNT(commission_pct)

FROM employees;

#需求:查询公司中平均奖金率

#错误的!因为commission_pct有NULL值,并不是所有人都有奖金,AVG只会计算那些有奖金的人的平均值

而题目要求的是所有人的平均奖金,应该是有奖金的人的奖金率 除以 公司总人数(而不是有奖金的人数)

SELECT AVG(commission_pct)

FROM employees;

#正确的:

SELECT SUM(commission_pct) / COUNT(IFNULL(commission_pct,0)),

AVG(IFNULL(commission_pct,0))

FROM employees;

#如果计算表中有多少条记录,如何实现?

#方式1:COUNT()
#方式2:COUNT(1)
#方式3:COUNT(具体字段) : 不一定对!因为count(
)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

如何需要统计表中的记录数,使用COUNT(*)、COUNT(1)、COUNT(具体字段) 哪个效率更高呢?

如果使用的是MyISAM 存储引擎,则三者效率相同,都是O(1) ,这种引擎内部有一计数器在维护着行数,直接取值就行

如果使用的是InnoDB 存储引擎,则三者效率:COUNT(*) = COUNT(1)> COUNT(字段)。

4)GROUP BY

用于将表中的数据分成若干组

1)在SELECT列表中所有未包含在组函数中的列都应该包含在GROUP BY子句中

2)GROUP BY 声明在FROM后面、WHERE后面,ORDER BY 前面、LIMIT前面

使用单个列分组:

#需求:查询各个部门的平均工资,最高工资

SELECT department_id,AVG(salary),SUM(salary)

FROM employees

GROUP BY department_id;

使用多个列分组:

#需求:查询各个department_id,job_id的平均工资

#方式1:

SELECT department_id,job_id,AVG(salary)

FROM employees

GROUP BY department_id,job_id;

5)HAVING

对分组之后的数据进行进一步过滤。

#要求1:如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE。否则,报错。 --> 聚合函数不能用在WHERE中

#要求2:HAVING 不能单独使用,必须要跟 GROUP BY 一起使用,HAVING 必须声明在 GROUP BY 的后面。

#要求3:当过滤条件中没有聚合函数时,则此过滤条件声明在WHERE中或HAVING中都可以。但是,建议大家声明在WHERE中。

#练习:查询各个部门中最高工资比10000高的部门信息

#错误的写法:

SELECT department_id,MAX(salary)

FROM employees

WHERE MAX(salary) > 10000

GROUP BY department_id;

#正确的写法:

SELECT department_id,MAX(salary)

FROM employees

GROUP BY department_id

HAVING MAX(salary) > 10000;

6)WHERE和HAVING的对比

1.HAVING必须和ORDER BY一起使用,WHERE不用

2.WHERE中不能使用聚合函数,HAVING可以

3.WHERE的执行顺序比HAVING靠前

4.如果过滤条件中没有聚合函数:这种情况下,WHERE的执行效率要高于HAVING

因为 WHERE 可以先筛选,用一个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。

HAVING 则需要先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用

的资源就比较多,执行效率也较低。

7)SELECT的执行过程

#SELECT 语句的完整结构

/*

#sql92语法:

SELECT ...,...,...(存在聚合函数)

FROM ...,...,...

WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件

GROUP BY ...,...

HAVING 包含聚合函数的过滤条件

ORDER BY ...,...(ASC / DESC )

LIMIT ...,...

#sql99语法:

SELECT ...,...,...(存在聚合函数)

FROM ... (LEFT / RIGHT)JOIN ...ON 多表的连接条件

(LEFT / RIGHT)JOIN ... ON ...

WHERE 不包含聚合函数的过滤条件

GROUP BY ...,...

HAVING 包含聚合函数的过滤条件

ORDER BY ...,...(ASC / DESC )

LIMIT ...,...

*/

需要记住 SELECT 查询时的两个顺序:

1.1 关键字的顺序是不能颠倒的: SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT...

1.2 SELECT 语句的执行顺序: FROM -> WHERE -> GROUP BY -> HAVING -> SELECT 的字段 -> DISTINCT -> ORDER BY -> LIMIT --> 先执行中间FROM到HAVING那块,然后执行SELECT,最后执行ORDER BY和LIMIT

在 SELECT 语句执行这些步骤的时候,每个步骤都会产生一个虚拟表,然后将这个虚拟表传入下一个步

骤中作为输入。需要注意的是,这些步骤隐含在 SQL 的执行过程中,对于我们来说是不可见的。

SELECT DISTINCT player_id, player_name, count(*) as num # 顺序 5

FROM player JOIN team ON player.team_id = team.team_id # 顺序 1

WHERE height > 1.80 # 顺序 2

GROUP BY player.team_id # 顺序 3

HAVING num > 2 # 顺序 4

ORDER BY num DESC # 顺序 6

LIMIT 2 # 顺序 7

8)SQL执行原理

SELECT 是先执行 FROM 这一步的。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:

  1. 首先先通过 CROSS JOIN 求笛卡尔积,相当于得到虚拟表 vt(virtual table)1-1;

  2. 通过 ON 进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2;

  3. 添加外部行。如果我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟

    表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3。

    当然如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得

    到是我们的原始数据。

    当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1 ,就可以在此基础上再进行 WHERE 阶

    段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2 。

    然后进入第三步和第四步,也就是 GROUP 和 HAVING 阶段。在这个阶段中,实际上是在虚拟表 vt2 的

    基础上进行分组和分组过滤,得到中间的虚拟表 vt3 和 vt4 。

    当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 SELECT 和 DISTINCT

    阶段。

    首先在 SELECT 阶段会提取想要的字段,然后在 DISTINCT 阶段过滤掉重复的行,分别得到中间的虚拟表

    vt5-1 和 vt5-2 。

    当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 ORDER BY 阶段,得到

    虚拟表 vt6 。

    最后在 vt6 的基础上,取出指定行的记录,也就是 LIMIT 阶段,得到最终的结果,对应的是虚拟表

    vt7 。

    当然我们在写 SELECT 语句的时候,不一定存在所有的关键字,相应的阶段就会省略。

    同时因为 SQL 是一门类似英语的结构化查询语言,所以我们在写 SELECT 语句的时候,还要注意相应的

    关键字顺序,所谓底层运行的原理,就是我们刚才讲到的执行顺序。

  4. 子查询

  5. 创建和管理表

  6. 数据处理之增删改

    1)添加数据

    方式1: 一条一条的添加数据:

    指明要添加的字段 (推荐)

    INSERT INTO emp1(id,hire_date,salary,name)

    VALUES(2,'1999-09-09',4000,'Jerry');

方式2: 同时插入多条记录 (推荐)

INSERT INTO emp1(id,NAME,salary)

VALUES

(4,'Jim',5000),

(5,'张俊杰',5500);

方式3: 将查询结果插入到表中

INSERT还可以将SELECT语句查询的结果插入到表中,此时不需要把每一条记录的值一个一个输入,只需

要使用一条INSERT语句和一条SELECT语句组成的组合语句即可快速地从一个或多个表中向一个表中插入

多行。

例子:

INSERT INTO emp1(id,NAME,salary,hire_date)

#查询语句

SELECT employee_id,last_name,salary,hire_date # 查询的字段一定要与添加到的表的字段一一对应

FROM employees

WHERE department_id IN (70,60);

  1. 更新数据 (或修改数据)

UPDATE ... SET ... WHERE ...

可以实现批量修改数据的。

例子:

修改一恶搞字段:

UPDATE emp1

SET hire_date = CURDATE()

WHERE id = 5;

#同时修改一条数据的多个字段:

UPDATE emp1

SET hire_date = CURDATE(),salary = 6000

WHERE id = 4;

  1. 删除数据
    DELETE FROM ... WHERE...

DELETE FROM emp1

WHERE id = 1;

#小结:DML操作默认情况下,执行完以后都会自动提交数据。

如果希望执行完以后不自动提交数据,则需要使用 SET autocommit = FALSE. --> 设置之后可以通过rollback回滚数据。

4)MySQL8的新特性:计算列

什么叫计算列呢?简单来说就是某一列的值是通过别的列计算得来的。例如,a列值为1、b列值为2,c列

不需要手动插入,定义a+b的结果为c的值,那么c就是计算列,是通过别的列计算得来的。

例子:

CREATE TABLE test1(

a INT,

b INT,

c INT GENERATED ALWAYS AS (a + b) VIRTUAL #字段c即为计算列

);

插入数据,c列的值会自动计算,存储在表中:

INSERT INTO test1(a,b)

VALUES(10,20);

  1. MySQL数据类型精讲

在定义数据类型时,如果确定是整数,就用INT ; 如果是小数,一定用定点数类型

DECIMAL(M,D) ; 如果是日期与时间,就用 DATETIME 。

本章直接参考课件。

  1. 约束

/*

  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 时增加约束、删除约束

*/

  1. 非空约束NOT NULL -- 限定某个字段/某列的值不允许为空
    默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
    非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
    一个表可以有很多列都分别限定了非空
    空字符串''不等于NULL,0也不等于NULL

在CREATE TABLE时添加约束:

CREATE TABLE test1(

id INT NOT NULL,

last_name VARCHAR(15) NOT NULL,

email VARCHAR(25),

salary DECIMAL(10,2)

);

在ALTER TABLE时添加约束:

ALTER TABLE test1

MODIFY email VARCHAR(25) NOT NULL;

在ALTER TABLE时删除约束:

ALTER TABLE test1

MODIFY email VARCHAR(25) NULL;

  1. 唯一性约束UNIQUE -- 用来限制某个字段/某列的值不能重复。

同一个表可以有多个唯一约束。

唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。

唯一性约束允许列值为空。

在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。

MySQL会给唯一约束的列上默认创建一个唯一索引。

在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)

);

在ALTER TABLE时添加约束:

#方式1:

ALTER TABLE test2

ADD CONSTRAINT uk_test2_sal UNIQUE(salary);

#方式2:

ALTER TABLE test2

MODIFY last_name VARCHAR(15) UNIQUE;

复合唯一约束: 多个列组成唯一性约束

例子:

CREATE TABLE USER(

id INT,
name VARCHAR(15),
password VARCHAR(25),

#表级约束

CONSTRAINT uk_user_name_pwd UNIQUE(name,password)

);

删除唯一性约束

-- 添加唯一性约束的列上也会自动创建唯一索引。

-- 删除唯一约束只能通过删除唯一索引的方式删除。

-- 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。

-- 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。

例子:

ALTER TABLE test2

DROP INDEX last_name;

  1. primary key (主键约束) -- 用来唯一标识表中的一行记录。

主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。

一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别上创建。

主键约束对应着表中的一列或者多列(复合主键)

如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。

MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。

当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询

的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了。

需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的

值,就有可能会破坏数据的完整性。

添加主键约束:

CREATE TABLE test4(

id INT PRIMARY KEY, #列级约束

last_name VARCHAR(15),

salary DECIMAL(10,2),

email VARCHAR(25)

);

在ALTER TABLE时添加约束:

CREATE TABLE test6(

id INT ,

last_name VARCHAR(15),

salary DECIMAL(10,2),

email VARCHAR(25)

);

ALTER TABLE test6

ADD PRIMARY KEY (id);

删除主键约束:

ALTER TABLE test6

DROP PRIMARY KEY;

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

在CREATE TABLE时添加

CREATE TABLE test7(

id INT PRIMARY KEY AUTO_INCREMENT,

last_name VARCHAR(15)

);

#开发中,一旦主键作用的字段上声明有AUTO_INCREMENT,则我们在添加数据时,就不要给主键

#对应的字段去赋值了。

INSERT INTO test7(last_name)

VALUES('Tom');

#当我们向主键(含AUTO_INCREMENT)的字段上添加0 或 null时,实际上会自动的往上添加指定的字段的数值

INSERT INTO test7(id,last_name)

VALUES(0,'Tom');

INSERT INTO test7(id,last_name)

VALUES(NULL,'Tom');

在ALTER TABLE 时添加:

CREATE TABLE test8(

id INT PRIMARY KEY ,

last_name VARCHAR(15)

);

在ALTER TABLE 时删除:

ALTER TABLE test8

MODIFY id INT;

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

Mysql5.7中,自增的列,比如id列,自增到了5,如果删除了id为5的列,然后重启mysql server,下一次添加新的数据,id会从5开始,

Mysql8中,id会从6开始。原因如下:

在MySQL 5.7系统中,对于自增主键的分配规则,是由InnoDB数据字典

内部一个计数器来决定的,而该计数器只在内存中维护,并不会持久化到磁盘中。当数据库重启时,该

计数器会被初始化,读取表中的数据,看现在到多少了。

MySQL 8.0将自增主键的计数器持久化到重做日志中。每次计数器发生改变,都会将其写入重做日志

中。如果数据库重启,InnoDB会根据重做日志中的信息来初始化计数器的内存值。

5)foreign key (外键约束) -- 限定某个表的某个字段的引用完整性。

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

主表(父表):被引用的表,被参考的表

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

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

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

主表,选课表是从表。

(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)删除外键约束后,必须手动删除对应的索引

创建外键约束:

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)

);

在ALTER TABLE时添加外键约束:

ALTER TABLE emp2

ADD CONSTRAINT fk_emp2_dept_id FOREIGN KEY(department_id) REFERENCES dept2(dept_id);

约束关系是针对双方的:

添加了外键约束后,主表的修改和删除数据受约束

添加了外键约束后,从表的添加和修改数据受约束

在从表上建立外键,要求主表必须存在

删除主表时,要求从表从表先删除,或将从表中外键引用该主表的关系先删除

约束等级:

-- 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)第一步先查看约束名和删除外键约束

SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';#查看某个

表的约束名

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

(2)第二步查看索引名和删除索引。(注意,只能手动删除)

SHOW INDEX FROM 表名称; #查看某个表的索引名

ALTER TABLE 从表名 DROP INDEX 索引名;

在 MySQL 里,外键约束是有成本的,需要消耗系统资源。对于大并发的 SQL 操作,有可能会不适

合。比如大型网站的中央数据库,可能会因为外键约束的系统开销而变得非常慢。所以, MySQL 允

许你不使用系统自带的外键约束,在应用层面完成检查数据一致性的逻辑。也就是说,即使你不

用外键约束,也要想办法通过应用层面的附加逻辑,来实现外键约束的功能,确保数据的一致性。

阿里开发规范:

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

说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学

生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单

机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响

数据库的插入速度。

6)check 约束 -- 检查某个字段的值是否符号xx要求,一般指的是值的范围

mysql8才支持。

CREATE TABLE test10(

id INT,

last_name VARCHAR(15),

salary DECIMAL(10,2) CHECK(salary > 2000) --> 薪水必须大于2000

);

#1500添加失败

INSERT INTO test10

VALUES(2,'Tom1',1500);

  1. DEFAULT约束 -- 给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默
    认值。

在CREATE TABLE添加约束:

CREATE TABLE test11(

id INT,

last_name VARCHAR(15),

salary DECIMAL(10,2) DEFAULT 2000

);

在ALTER TABLE添加约束:

CREATE TABLE test12(

id INT,

last_name VARCHAR(15),

salary DECIMAL(10,2)

);

在ALTER TABLE删除约束

ALTER TABLE test12

MODIFY salary DECIMAL(8,2);

相关推荐
影子240124 分钟前
Navicat导出mysql数据库表结构说明到excel、word,单表导出方式记录
数据库·mysql·excel
lwewan2 小时前
26考研——栈、队列和数组_数组和特殊矩阵(3)
数据结构·笔记·考研·算法
wei3872452323 小时前
java笔记02
java·开发语言·笔记
要天天开心啊3 小时前
MyBatis第二天笔记
笔记·tomcat·mybatis
枫林血舞4 小时前
python笔记之函数
笔记·python
悄悄敲敲敲5 小时前
C++第13届蓝桥杯省b组习题笔记
c++·笔记·算法·蓝桥杯
开发小能手-roy6 小时前
ubuntu 安装mysql
mysql·ubuntu·adb
V---scwantop---信6 小时前
热门索尼S-Log3电影感氛围旅拍LUTS调色预设 Christian Mate Grab - Sony S-Log3 Cinematic LUTs
笔记
Long_poem6 小时前
【自学笔记】PHP语言基础知识点总览-持续更新
android·笔记·php
是阿建吖!7 小时前
【MySQL】事务
数据库·mysql