MySQL
1 数据库相关概念
1.1 数据库
Database,简称DB。按照一定的数据结构来组织、存储和管理数据仓库。
1.2 数据库管理系统
Database Management System,一种操纵和管理数据库的大型软件,用于创建、使用和维护数据库,简称DBMS。
1.2.1 关系型数据库(RDBMS):
概念:关系型数据库是建立在关系模型基础上,由多张相互连接的二维表组成的数据库。
1.2.2 非关系型数据库(NoSQL):
概念:Not-Only SQL,泛指非关系型数据库,是关系型数据库的补充。
1.3 MySQL数据库
注:简单环境变量设置,将 将MySQL Server的安装目录下的bin目录添加到环境变量。
1.3.1 MySQL 服务器启动与停止
(1)通过服务的方式自动启动:
右击此电脑,选择管理,选择服务和应用程序,找到MYSQL右击启动。
(2) 手动启动的方式:
cmd–> services.msc 打开服务的窗口
(3)使用管理员身份打开cmd(mysql80为默认指定的mysql的系统服务名)
net start mysql80 : 启动mysql的服务
net start mysql80
net stop mysql80 : 关闭mysql服务
net stop mysql80
(4) 退出
quit 或 exit;
1.3.2 客户端连接
1) 方式一:使用MySQL提供的客户端命令行工具
2) 方式二:使用系统自带的命令行工具执行指令
mysql [-h 127.0.0.1] [-P 3306] -u root -p |
2 SQL
全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了
一套操作关系型数据库统一标准。
2.1 SQL语言的通用语法:
1) SQL语句可以单行或多行书写,以分号结尾。
2) SQL语句可以使用空格/缩进来增强语句的可读性。
3) MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。
4) 注释:
单行注释:— 注释内容 或 # 注释内容
多行注释:/ 注释内容 /
2.2 SQL分类
SQL语句,根据其功能,主要分为四类:DDL、DML、DQL、DCL。
分类 | 全称 | 说明 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,用来定义数据库对象(数据库,表,字段) |
DML | Data Manipulation Language | 数据操作语言,用来对数据库表中的数据进行增删改 |
DQL | Data Query Languag | 数据查询语言,用来查询数据库中表的记录 |
DCL | Data Control Language | 数据控制语言,用来创建数据库用户、控制数据库的访问权限 |
2.3 DDL操作数据库
2.3.1 数据库操作
1)查询所有数据库
SHOW DATABASES; |
2)查询当前数据库
SELECT DATABASE(); |
3)创建数据库
CREATE DATABASE IF NOT EXISTS ] 数据库名 [ DEFAULT CHARSET 字符集 ] [ COLLATE 排序规则 ]; |
4)删除数据库
DROP DATABASE [ IF EXISTS ] 数据库名 ; |
5)切换(使用)数据库
USE 数据库名; |
2.3.2 表操作
2.3.2.1 表操作—查询创建
1)查询当前数据库所有表
SHOW TABLES; |
2)查询指定表结构
DESC 表名; |
3)查看指定表的建表语句
SHOW CREATE TABLE 表名; |
4)创建表结构
CREATE TABLE 表名( |
2.3.2.2 表操作—数据类型
MySQL中的数据类型有很多,主要分为三类:数值类型、字符串类型、日期时间类型。
1)数值类型
类型 | 大小 | 有符号(SIGNED)范围 | 无符号(UNSIGNED)范围 | 描述 |
---|---|---|---|---|
TINYINT | 1 byte | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2 byte | (-32768,32767) | (0,65535) | 大整数值 |
MEDIUMINT | 3 byte | (-8388608,8388607) | (0,16777215) | 大整数值 |
INT或INTEGER | 4 byte | (-2147483648,2147483647) | (0,4294967295) | 大整数值 |
BIGINT | 8 bytes | (-2^63^,2^63^-1) | (0,2^64^-1) | 极大整数值 |
FLOAT | 4 bytes | (-3.402823466 E+38,3.402823466351 E+38) | 0 和 (1.175494351 E-38,3.402823466 E+38) | 单精度浮点数值 |
DOUBLE | 8 bytes | (-1.7976931348623157 E+308,1.7976931348623157 E+308) | 0 和 (2.2250738585072014 E-308,1.7976931348623157 E+308) | 双精度浮点数值 |
DECIMAL | 依赖于M(精度)和D(标度)的值 | 依赖于M(精度)和D(标度)的值 | 小数值(精确定点数) |
- 注:age TINYINT UNSIGNED
- score double(4, 1),长度为4,小数1位
2)字符串类型
类型 | 大小 | 描述 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串 |
VARCHAR | 0-65535 bytes | 变长字符串 |
TINYBLOB | 0-255 bytes | 不超过255个字符的二进制数据 |
TINYTEXT | 0-255 bytes | 短文本字符串 |
BLOB | 0-65 535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65 535 bytes | 长文本数据 |
MEDIUMBLOB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215 bytes | 中等长度文本数据 |
LONGBLOB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295 bytes | 极大文本数据 |
/* |
类型 | 大小 | 范围 | 格式 | 描述 |
---|---|---|---|---|
DATE | 3 | 1000-01-01 至 9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | -838:59:59 至 838:59:59 | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901 至 2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:01 至 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,时间戳 |
/* |
2.3.2.3 表操作—修改
1)添加字段
ALTER TABLE 表名 ADD 字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ]; |
2)修改数据类型
ALTER TABLE 表名 MODIFY 字段名 新数据类型 (长度); |
3)修改字段名和字段类型
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ]; |
4)删除字段
ALTER TABLE 表名 DROP 字段名; |
5)修改表名
ALTER TABLE 表名 RENAME TO 新表名; |
2.3.2.2 表操作—删除
1)删除表
DROP TABLE [ IF EXISTS ] 表名; |
2)删除指定表,并重新创建该表
TRUNCATE TABLE 表名;-- 注意: 在删除表的时候,表中的全部数据也都会被删除。 |
2.4 MySQL图形化界面(DataGrip)
下载官网:https://www.jetbrains.com/zh-cn/datagrip/promo/
2.5 DML
DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增、删、改操作。
- 添加数据(INSERT)
- 修改数据(UPDATE)
- 删除数据(DELETE)
2.5.1 添加数据
1)给指定字段添加数据
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...); |
2)给全部字段添加数据
INSERT INTO 表名 VALUES (值1, 值2, ...); |
3)批量添加数据
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...) ; |
INSERT INTO 表名 VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...) ; |
INSERT INTO employee VALUES(3,'3','韦一笑','男',38,'123456789012345670','2005-01-01'),(4,'4','赵敏','女',18,'123456789012345670','2005-01-01'); |
注意事项:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
- 字符串和日期型数据应该包含在引号中。
- 插入的数据大小,应该在字段的规定范围内。
2.5.2 修改数据
UPDATE 表名 SET 字段名1 = 值1 , 字段名2 = 值2 , .... [ WHERE 条件 ] ; |
#案例 |
2.5.3 删除数据
DELETE FROM 表名 [ WHERE 条件 ] ; |
#案列 |
注意事项:
- DELETE 语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据。
- DELETE 语句不能删除某一个字段的值(可以使用UPDATE,将该字段值置为NULL即可)。
- 当进行删除全部数据操作时,datagrip会提示我们,询问是否确认删除,我们直接点击Execute即可。
2.6 DQL
DQL英文全称是Data Query Language(数据查询语言),数据查询语言,用来查询数据库中表的记录。
- 查询关键字: SELECT
2.6.1 基本语法
SELECT |
- 基本查询(不带任何条件)
- 条件查询(WHERE)
- 聚合函数(count、max、min、avg、sum)
- 分组查询(group by)
- 排序查询(order by)
- 分页查询(limit)
2.6.2 基本查询
1)查询多个字段
SELECT 字段1, 字段2, 字段3 ... FROM 表名 ; |
SELECT * FROM 表名 ; |
2) 字段设置别名
SELECT 字段1 [ AS 别名1 ] , 字段2 [ AS 别名2 ] ... FROM 表名; |
SELECT 字段1 [ 别名1 ] , 字段2 [ 别名2 ] ... FROM 表名; |
3)去除重复记录
SELECT DISTINCT 字段列表 FROM 表名; |
#案例: |
2.6.3 条件查询
SELECT 字段列表 FROM 表名 WHERE 条件列表 ; |
条件
| 比较运算符 | 功能 |
| :————————-: | :———————————————————: |
| > | 大于 |
| >= | 大于等于 |
| < | 小于 |
| <= | 小于等于 |
| = | 等于 |
| <> 或 != | 不等于 |
| BETWEEN … AND … | 在某个范围之内(含最小、最大值) |
| IN(…) | 在in之后的列表中的值,多选一 |
| LIKE 占位符 | 模糊匹配(_匹配单个字符, %匹配任意个字符) |
| IS NULL | 是NULL |
常用逻辑运算符
| 逻辑运算符 | 功能 |
| :————: | :————————————-: |
| AND 或 && | 并且 (多个条件同时成立) |
| OR 或 || | 或者 (多个条件任意一个成立) |
| NOT 或 ! | 非 , 不是 |
#案例: |
2.6.4 聚合函数
将一列数据作为一个整体,进行纵向计算 。
SELECT 聚合函数(字段列表) FROM 表名 ; |
- 注意 : NULL值是不参与所有聚合函数运算的。
#案例 |
对于count聚合函数,统计符合条件的总记录数,还可以通过 count(数字/字符串)的形式进行统计
查询,比如:
SELECT COUNT(1) FROM emp; |
-- 统计该企业员工的平均年龄 |
2.6.5 分组查询
1)语法
SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ]; |
2)where与having区别
执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
判断条件不同:where不能对聚合函数进行判断,而having可以。
注意事项:
- 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义。
- 执行顺序: where > 聚合函数 > having 。
- 支持多字段分组, 具体语法为 : group by columnA,column
-- 根据性别分组 , 统计男性员工和女性员工的数量 |
2.6.6 排序查询
1)语法
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1 , 字段2 排序方式2 ; |
2)排序方式
- ASC : 升序(默认值)
- DESC: 降序
注意事项:
- 如果是升序, 可以不指定排序方式ASC ;
- 如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序 ;
#案例: |
2.6.7 分页查询
语法
SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数 ; |
注意事项:
- 起始索引从0开始,起始索引 = (查询页码 - 1)* 每页显示记录数。
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT。
- 如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 10。
#案例: |
2.6.8 案例练习
-- 查询年龄为20,21,22,23岁的女性员工信息。 |
2.6.9 执行顺序
#验证 |
2.7 DCL
DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。
2.7.1 管理用户
1)查询用户
USE mysql; |
其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问,是不可以
远程访问的。 User代表的是访问该数据库的用户名。在MySQL中需要通过Host和User来唯一标识一
个用户。
2)创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码'; |
3)修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码' ; |
4)删除用户
DROP USER '用户名'@'主机名' ; |
注意事项:
- 在MySQL中需要通过 用户名@主机名的方式,来唯一标识一个用户。
- 主机名可以使用 % 通配。
- 这类SQL开发人员操作的比较少,主要是DBA( Database Administrator 数据库
管理员)使用
-- 创建用户itxie, 只能够在当前主机localhost访问, 密码123456; |
2.7.2 权限控制
MySQL中定义了很多种权限,但是常用的就以下几种:
权限 | 说明 |
---|---|
ALL, ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
官方文档:https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html
1)查询权限
SHOW GRANTS FOR '用户名'@'主机名' ; |
2)授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名'; |
3)撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名'; |
注意事项:
- 多个权限之间,使用逗号分隔
- 授权时, 数据库名和表名可以使用 * 进行通配,代表所有。
-- 查询 'xie'@'%' 用户的权限 |
3 函数
函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着,这一段程序或代码在MySQL中
已经给我们提供了,我们要做的就是在合适的业务场景调用对应的函数完成对应的业务需求即可。
3.1 字符串函数
MySQL中内置了很多字符串函数,常用的几个如下:
函数 | 功能 |
---|---|
CONCAT(S1,S2,…Sn) | 字符串拼接,将S1,S2,… Sn拼接成一个字符串 |
LOWER(str) | 将字符串str全部转为小写 |
UPPER(str) | 将字符串str全部转为大写 |
LPAD(str,n,pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 |
RPAD(str,n,pad) | 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度 |
TRIM(str) | 去掉字符串头部和尾部的空格 |
SUBSTRING(str,start,len) | 返回从字符串str从start位置起的len个长度的字符串 |
-- concat : 字符串拼接 |
3.2 数值函数
函数 | 功能 |
---|---|
CEIL(x) | 向上取整 |
FLOOR(x) | 向下取整 |
MOD(x,y) | 返回x/y的模 |
RAND() | 返回0~1内的随机数 |
ROUND(x,y) | 求参数x的四舍五入的值,保留y位小数 |
-- ceil:向上取整 |
3.3 日期函数
函数 | 功能 |
---|---|
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
YEAR(date) | 获取指定date的年份 |
MONTH(date) | 获取指定date的月份 |
DAY(date) | 获取指定date的日期 |
DATE_ADD(date, INTERVAL expr type) | 返回一个日期/时间值加上一个时间间隔expr后的时间值 |
DATEDIFF(date1,date2) | 返回起始时间date1 和 结束时间date2之间的天数 |
-- curdate:当前日期 |
3.4 流程函数
流程函数也是很常用的一类函数,可以在SQL语句中实现条件筛选,从而提高语句的效率。
函数 | 功能 |
---|---|
IF(value , t , f) | 如果value为true,则返回t,否则返回f |
IFNULL(value1 , value2 | 如果value1不为空,返回value1,否则返回value2 |
CASE WHEN [ val1 ] THEN [res1] …ELSE [ default ] END | 如果val1为true,返回res1,… 否则返回default默认值 |
CASE [ expr ] WHEN [ val1 ] THEN[res1] … ELSE [ default ] END | 如果expr的值等于val1,返回res1,… 否则返回default默认值 |
-- if |
4 约束
4.1 概述
1)概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
2)目的:保证数据库中数据的正确、有效性和完整性。
3)分类
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束(8.0.16版本之后) | 保证字段值满足某一个条件 | CHECK |
外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
- 注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束
4.2 约束演示
案例需求:
字段名 | 字段含义 | 字段类型 | 约束条件 | 约束关键字 |
---|---|---|---|---|
id | ID唯一标识 | int | 主键并且自动增长 | PRIMARY KEY ,AUTO_INCREMENT |
name | 姓名 | varchar(10) | 非空且唯一 | NOT NULL , UNIQUE |
age | 年龄 | int | 大于0且小于等于120 | CHECK |
status | 状态 | char(1) | 如没有指定值,默认为1 | DEFAULT |
gender | 性别 | char(1) | 无 |
CREATE TABLE user( |
4.3 外键约束
4.3.1 介绍
外键:用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。
准备数据:
create table dept( |
4.3.2 语法
1)添加外键
CREATE TABLE 表名( |
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表 (主表列名) ; |
案例:为emp表的dept_id字段添加外键约束,关联dept表的主键id。
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept (id); |
添加了外键约束之后,我们再到dept表(父表)删除id为1的记录,然后看一下会发生什么现象。 此时
将会报错,不能删除或更新父表记录,因为存在外键约束。
2)删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称; |
案列:删除emp表的外键fk_emp_dept_id。
ALTER TABLE emp DROP FOREIGN KEY fk_emp_dept_id; |
4.3.3 删除/更新行为
添加了外键之后,再删除父表数据时产生的约束行为,我们就称为删除/更新行为。具体的删除/更新行
为有以下几种:
行为 | 说明 |
---|---|
NO ACTION | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键, 如果有则不允许删除/更新。 (与 RESTRICT 一致) 默认行为 |
RESTRICT | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键, 如果有则不允许删除/更新。 (与 NO ACTION 一致) 默认行为 |
CASCADE | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键, 如果有,则也删除/更新外键在子表中的记录 |
SET NULL | 当在父表中删除对应记录时,首先检查该记录是否有对应外键, 如果有则设置子表中该外键值为null(这就要求该外键允许取null) |
SET DEFAULT | 父表有变更时,子表将外键列设置成一个默认的值 (Innodb不支持) |
具体语法为:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名 (主表字段名) ON UPDATE CASCADE ON DELETE CASCADE; |
1)CASCADE
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept (id) ON UPDATE CASCADE ON DELETE CASCADE ; -- 级联更新 |
2)SET NULL
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept (id) ON UPDATE SET NULL ON DELETE SET NULL ; -- 级联更新为null |
5 多表查询
5.1 多表关系
项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结
构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:
一对多(多对一)
多对多
一对一
5.1.1 一对多
- 案例: 部门 与 员工的关系
- 关系: 一个部门对应多个员工,一个员工对应一个部门
- 实现: 在多的一方建立外键,指向一的一方的主键
5.1.2 多对多
案例: 学生 与 课程的关系
关系: 一个学生可以选修多门课程,一门课程也可以供多个学生选择
实现: 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
create table student( |
5.1.3 一对一
- 案例: 用户 与 用户详情的关系
- 关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率、
- 实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)
create table tb_user( |
5.2 多表查询概述
5.2.1 数据准备
1)删除之前 emp, dept表的测试数据
2)执行如下脚本,创建emp表与dept表并插入测试数据
-- 创建dept表,并插入数据 |
5.22 概述
多表查询就是指从多张表中查询数据。
要执行多表查询,就只需要使用逗号分隔多张表即可,如: select * from emp , dept; 具体的执行结果如下:
此时,我们看到查询结果中包含了大量的结果集,总共102条记录,而这其实就是员工表emp所有的记录(17) 与 部门表dept所有记录(6) 的所有组合情况,这种现象称之为笛卡尔积。接下来,就来简单介绍下笛卡尔积。
笛卡尔积: 笛卡尔乘积是指在数学中,两个集合A集合 和 B集合的所有组合情况。
而在多表查询中,我们是需要消除无效的笛卡尔积的,只保留两张表关联部分的数据。
我们可以给多表查询加上连接查询的条件即可去除无效的笛卡尔积:
SELECT * FROM emp,dept WHERE dept_id = dept.id; |
5.2.3 分类
1)连接查询
- 内连接:相当于查询A、B交集部分数据
- 外连接:
左外连接:查询左表所有数据,以及两张表交集部分数据
右外连接:查询右表所有数据,以及两张表交集部分数据 - 自连接:当前表与自身的连接查询,自连接必须使用表别名
2)子查询
5.3 内连接
内连接查询的是两张表交集部分的数据。
内连接的语法分为两种: 隐式内连接、显式内连接。
1)隐式内连接
SELECT 字段列表 FROM 表1 , 表2 WHERE 条件 ... ; |
2)显式内连接
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 连接条件 ... ; |
案例:
-- A.查询每一个员工的姓名 , 及关联的部门的名称 (隐式内连接实现) |
注:表的别名:
①. tablea as 别名1 , tableb as 别名2 ;
②. tablea 别名1 , tableb 别名2 ;
- 一旦为表起了别名,就不能再使用表名来指定对应的字段了,此时只能够使用别名来指定字段。
5.4 外连接
外连接分为两种,分别是:左外连接 和 右外连接。具体的语法结构为:
1)左外连接
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 条件 ... ; |
左外连接相当于查询表1(左表)的所有数据,当然也包含表1和表2交集部分的数据。
2)右外连接
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 ... ; |
右外连接相当于查询表2(右表)的所有数据,当然也包含表1和表2交集部分的数据。
案例:
-- A.查询每一个员工的姓名 , 及关联的部门的名称 (隐式内连接实现) |
注意事项:
- 左外连接和右外连接是可以相互替换的,只需要调整在连接查询时SQL中,表结构的先后顺序就可以了。而我们在日常开发使用时,更偏向于左外连接。
5.5 自连接
5.5.1 自连接查询
自连接查询,顾名思义,就是自己连接自己,也就是把一张表连接查询多次。查询语法:
SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 ... ; |
而对于自连接查询,可以是内连接查询,也可以是外连接查询。
案例:
-- 查询员工 及其 所属领导的名字 |
注意事项:
- 在自连接查询中,必须要为表起别名,要不然我们不清楚所指定的条件、返回的字段,到底是哪一张表的字段。
5.5.2 联合查询
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
SELECT 字段列表 FROM 表A ... |
- 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
- union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。
-- 将薪资低于 5000 的员工 , 和 年龄大于 50 岁的员工全部查询出来 |
注意:
- 如果多条查询语句查询出来的结果,字段数量不一致,在进行union/union all联合查询时,将会报
错。
5.6 子查询
5.6.1 概述
1)概念
SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询。
SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 ); |
子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个。
2)分类
根据子查询结果不同,分为:
- 标量子查询(子查询结果为单个值)
- 列子查询(子查询结果为一列)
- 行子查询(子查询结果为一行)
- 表子查询(子查询结果为多行多列)
根据子查询位置,分为:
- WHERE之后
- FROM之后
- SELECT之后
5.6.2 标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。
常用的操作符:= <> > >= < <=。
案例:
-- 查询 "销售部" 的所有员工信息 |
5.6.3 列子查询
子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。
常用的操作符:IN 、NOT IN 、 ANY 、SOME 、 ALL
操作符 | 描述 |
---|---|
IN | 在指定的集合范围之内,多选一 |
NOT IN | 不在指定的集合范围之内 |
ANY | 子查询返回列表中,有任意一个满足即可 |
SOME | 与ANY等同,使用SOME的地方都可以使用ANY |
ALL | 子查询返回列表的所有值都必须满足 |
案例:
-- 查询 "销售部" 和 "市场部" 的所有员工信息 |
5.6.4 行子查询
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。
常用的操作符:= 、<> 、IN 、NOT IN
案例:
-- 查询与 "张无忌" 的薪资及直属领导相同的员工信息 |
5.6.5 表子查询
子查询返回的结果是多行多列,这种子查询称为表子查询。常用的操作符:IN
-- 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息 |
5.7 多表查询案例
-- 多表查询案例 |
6 事务
6.1 事务简介
事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
就比如: 张三给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加1000。 这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。
注意: 默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐
式的提交事务。
6.2 事务操作
数据准备:
drop table if exists account; |
6.2.1 控制事务一
1)查看/设置事务提交方式
SELECT @@AUTOCOMMIT; |
2)提交事务
COMMIT ; |
3)回滚事务
ROLLBACK ; |
注意:上述的这种方式,我们是修改了事务的自动提交行为, 把默认的自动提交修改为了手动提交, 此时我们执行的DML语句都不会提交, 需要手动的执行commit进行提交。
6.2.2 控制事务二
1)开启事务
START TRANSACTION ; |
2)提交事务
COMMIT ; |
3)回滚事务
ROLLBACK ; |
6.3 事务四大特性
- 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
- 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
上述就是事务的四大特性,简称ACID
6.4 事务并发问题
1)脏读:一个事务读到另外一个事务还没有提交的数据(读到了另一个事务没有commit的数据)。
2)不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读(先后查询到另一个事务commit前后的数据不一致)。
3)幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 “幻影”。(另一事务插入数据commit了,而这个事务没有查询到数据,但是插入数据发现又在,commit后才能查到)
6.5 事务隔离级别
为了解决并发事务所引发的问题,在数据库中引入了事务隔离级别。主要有以下几种:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed(Oracle默认) | × | √ | √ |
Repeatable Read(MySQL默认) | × | × | √ |
Serializable | × | × | × |
1)查看事务隔离级别
SELECT @@TRANSACTION_ISOLATION; |
2)设置事务隔离级别
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } |
注意:事务隔离级别越高,数据越安全,但是性能越低。
7 存储引擎
7.1 MySQL体系架构
1)连接层
最上层是一些客户端和链接服务,包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
2)服务层
第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如 过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询的顺序,是否利用索引等,最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。
3)引擎层
存储引擎层, 存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。数据库中的索引是在存储引擎层实现的。
4)存储层
数据存储层, 主要是将数据(如: redolog、undolog、数据、索引、二进制日志、错误日志、查询日志、慢查询日志等)存储在文件系统之上,并完成与存储引擎的交互。
和其他数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎上,插件式的存储引擎架构,将查询处理和其他的系统任务以及数据的存储提取分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
7.2 存储引擎介绍
存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。我们可以在创建表的时候,来指定选择的存储引擎,如果没有指定将自动选择默认的存储引擎。
1)建表时指定存储引擎
CREATE TABLE 表名( |
2)查询当前数据库支持的存储引擎
SHOW ENGINES; |
7.3 存储引擎特点
7.3.1 InnoDB
1)介绍
InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在 MySQL 5.5 之后,InnoDB是默认的MySQL 存储引擎。
2)特点
- DML操作遵循ACID模型,支持事务;
- 行级锁,提高并发访问性能;
- 支持外键FOREIGN KEY约束,保证数据的完整性和正确性;
3)文件
xxx.ibd:xxx代表的是表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm-早期的 、sdi-新版的)、数据和索引。
参数:innodb_file_per_table
show variables like 'innodb_file_per_table'; |
如果该参数开启,代表对于InnoDB引擎的表,每一张表都对应一个ibd文件。 我们直接打开MySQL的数据存放目录:C:\ProgramData\MySQL\MySQL Server 8.0\Data , 这个目录下有很多文件夹,不同的文件夹代表不同的数据库,我们直接打开itxie01文件夹。
可以看到里面有很多的ibd文件,每一个ibd文件就对应一张表,比如:我们有一张表 account,就有这样的一个account.ibd文件,而在这个ibd文件中不仅存放表结构、数据,还会存放该表对应的索引信息。 而该文件是基于二进制存储的,不能直接基于记事本打开,我们可以使用mysql提供的一个指令 ibd2sdi ,通过该指令就可以从ibd文件中提取sdi信息,而sdi数据字典信息中就包含该表的表结构。(使用命令行打开)
4)逻辑存储结构
- 表空间 : InnoDB存储引擎逻辑结构的最高层,ibd文件其实就是表空间文件,在表空间中可以包含多个Segment段。
- 段 : 表空间是由各个段组成的, 常见的段有数据段、索引段、回滚段等。InnoDB中对于段的管理,都是引擎自身完成,不需要人为对其控制,一个段中包含多个区。
- 区 : 区是表空间的单元结构,每个区的大小为1M。 默认情况下, InnoDB存储引擎页大小为16K, 即一个区中一共有64个连续的页。
- 页 : 页是组成区的最小单元,页也是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。为了保证页的连续性,InnoDB 存储引擎每次从磁盘申请 4-5 个区。
- 行 : InnoDB 存储引擎是面向行的,也就是说数据是按行进行存放的,在每一行中除了定义表时所指定的字段以外,还包含两个隐藏字段。
7.3.2 MyISAM
1)介绍
MyISAM是MySQL早期的默认存储引擎。
2)特点
- 不支持事务,不支持外键
- 支持表锁,不支持行锁
- 访问速度快
3)文件
- xx.sdi:存储表结构信息
- xxx.MYD: 存储数据
- xxx.MYI: 存储索引
7.3.3 Memory
1)介绍
Memory引擎的表数据时存储在内存中的,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用。
2)特点
- 内存存放
- hash索引(默认)
3)文件
xxx.sdi:存储表结构信息
7.3.4 区别及特点
特点 | InnoDB | MyISAM | Memory |
---|---|---|---|
存储限制 | 64TB | 有 | 有 |
事务安全 | 支持 | - | - |
锁机制 | 行锁 | 表锁 | 表锁 |
B+Tree索引 | 支持 | 支持 | 支持 |
hash索引 | - | - | 支持 |
全文索引 | 支持(5.6版本之后) | 支持 | - |
空间使用 | 高 | 低 | N/A |
内存使用 | 高 | 低 | 中等 |
批量插入速度 | 低 | 高 | 高 |
支持外键 | 支持 | - | - |
面试题:
InnoDB引擎与MyISAM引擎的区别 ?
①. InnoDB引擎, 支持事务, 而MyISAM不支持。
②. InnoDB引擎, 支持行锁和表锁, 而MyISAM仅支持表锁, 不支持行锁。
③. InnoDB引擎, 支持外键, 而MyISAM是不支持的。
主要是上述三点区别,当然也可以从索引结构、存储限制等方面,更加深入的回答,具体参考如下官方文档:
https://dev.mysql.com/doc/refman/8.0/en/innodb-introduction.html
https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html
7.4 存储引擎选择
在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据
实际情况选择多种存储引擎进行组合。
- InnoDB: 是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。
- MyISAM : 如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。
- MEMORY:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。
8 索引
8.1 索引概述
8.1.1 介绍
索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足
特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构
上实现高级查找算法,这种数据结构就是索引。