全网最全MySQL知识点万字整理

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 人和人交流需要语言,人和数据库交流也需要语言,而这个专门特定为程序员和数据库打交道的语言就是 SQL 语言。 SQL:结构化查询语言(Structured Query Language)。是关系型数据库标准语言。 特点:简单,灵活,功能强大。

1.JPG


一、SQL介绍


1.1、SQL概述


   人和人交流需要语言,人和数据库交流也需要语言,而这个专门特定为程序员和数据库打交道的语言就是 SQL 语言。


   SQL:结构化查询语言(Structured Query Language)。是关系型数据库标准语言。 特点:简单,灵活,功能强大。


1.2、SQL包含的6个部分


1.2.1、数据查询语言(DQL)


   其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字 SELECT 是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHEREORDER BYGROUP BYHAVING。这些 DQL 保留字常与其他类型的SQL语句一起使用。


1.2.2、数据操作语言(DML)


   其语句包括动词 INSERTUPDATEDELETE。它们分别用于添加,修改和删除表中的行。也称为动作语言。


1.2.3、数据定义语言(DDL)


   其语句包括动词 CREATE 和 DROP。在数据库中创建新表或删除表(CREAT TABLE DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。



1.2.4、事务处理语言(TPL)


   它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTIONCOMMITROLLBACK


1.2.5、数据控制语言(DCL)


   它的语句通过GRANTREVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANTREVOKE控制对表单个列的访问。


1.2.6、指针控制语言(CCL)


   它的语句,像DECLARE CURSORFETCH INTOUPDATE WHERE CURRENT用于对一个或多个表单独行的操作。


1.3、书写规则


  1. 数据库中,SQL 语句大小写不敏感. 如: select、SELECT.、SeleCt,为了提高可读性,一般关键字大写,其他小写
  2. SQL 语句可单行或多行书写,用分号来分辨是否结束。
  3. 合理利用空格和缩进使程序易读


二、表和ORM


2.1、表


    二维表是 同类实体 的各种 属性的集合,每个实体对应于表中的一行,在关系中称为元组,相当于通常的一条记录; 表中的列表示属性,称为Field,相当于通常记录中的一个数据项,也叫列、字段。 行: 表示一个实体,一条记录 列: 字段,数据项。


2.2、表和对象的关系(ORM)


ORM: Oject Reraltional Mapping : 对象表的映射


    在开发中,我们需要将表中的数据查询出来保存到内存中,或者把内存中的数据保存到数据库中,此时就需要将数据表的数据和Java中的对象进行映射关联起来。这种映射关联就称为 ORM 思想。


2.JPG3.JPG


三、MySQL服务


3.1、MySQL服务


打开数据库连接之前:一定要保证 MySQL 服务已经开启了。

net start命令开启一个服务,如:net start MySQL。

net stop 命令关闭一个服务器,如:net stop MySQL


3.2、连接MySQL


方式一

进入 MySQL 自带的客户端, 在命令行中输入密码。


方式二

在运行(win + r 进入cmd )中输入命令。


格式:mysql -u账户 -p密码 -h数据库服务器安装的主机 -P数据库端口

mysql -uroot -padmin -h127.0.0.1 -P3306
复制代码

 

 若连接的数据库服务器在本机上,并且端口是 3306。 则可以简写: mysql -uroot -padmin。


四、数据库基础


4.1、数据库基本操作


  1. 查看数据库服务器存在哪些数据库.:SHOW DATABASES
  2. 使用指定的数据库.:USE database_name
  3. 查看指定的数据库中有哪些数据表:SHOW TABLES
  4. 创建指定名称的数据库.:CREATE DATABASE database_name
  5. 删除数据库:DROP DATABASE database_name


4.2、存储引擎


   MySQL 中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供不同的功能和能力。 通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能。

   

简单来说,存储引擎是表的存储方式。


    MySQL常用存储引擎:

  • MyISAM:拥有较高的插入,查询速度,但不支持事务,不支持外键。
  • InnoDB:支持事务,支持外键,支持行级锁定,性能较低。最安全

 

 InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但对比MyISAM,处理效率差,且会占用更多的磁盘空间以保留数据和索引。一个系统,特别是金融系统,没有事务是很恐怖的事情,一般都要选择 InnDB。


4.JPG


五、MySQL列的常用类型


5.1、最常用的类型


MsSQL Java
INT int
BIGINT long
DECIMAL BigDecimal
DATE/DATETIME java.util.Date
VARCHAR String


5.2、整数类型


   整数类型有宽度指示器,作用是指定位宽。


   例如:某字段类型为 INT(3),保证少于3个值,从数据库检索出来时能够自动地用 0 填充,需设置填充,默认不填充。


宽度指示器不影响列存值得范围。一般不指定位宽。

5.JPG

5.3、小数 类型


FLOAT[(s,p)] DOUBLE[(s,p)]: 小数类型,可存放实型和整型 ,精度 (p) 和范围 (s)。


DECIMAL : 高精度类型,金额货币优先选择。


6.JPG


5.4、字符类型


  • char(size) : 定长字符,0 - 255字节,size 指 N 个字符数,若插入字符数超过设定长度,会被截取并警告。
  • varchar(size): 变长字符,0 - 255字节,从 MySQL5 开始支持 65535 个字节,若插入字符数超过设定长度,在非严格模式下会被截取并警告。


7.JPG

 

一般存储大量的字符串,比如文章的纯文本,可以选用 TEXT 系列类型,这个系列都是变长的。


   注意: 在 MySQL 中,字符类型必须指定长度,值要使用 单引号引起来。 相当于Java中字符(String,StringBuilder/StringBuffer);


8.JPG


5.5、日期类型


   常用日期和时间类型: DATE、DATETIME。


   注意: 在 MySQL 中,日期时间值使用单引号引起来。 相当于 Java中 Date,Calender。


9.JPG

5.6、二进制类型


   二进制类型主要用于存放图形、声音和影像,二进制对象,0-4GB。


   开发中,我们一般存储二进制文件保存路径,所以以上的类型非特殊需求不会使用。

   BIT,一般存储 0 或 1,存储是 Java 中的 boolean/Boolean 类型的值(需要使用)。


10.JPG


六、表的操作(DDL)


   表的操作主要是使用 DDL 来创建表和删除表等操作


6.1、创建表


6.1.1、语法


CREATE TABLE 表名 (
  列名1 列的类型 [约束],
  列名2 列的类型 [约束],
  ....
  列名N 列的类型 约束
);
-- 注意:最后一行没有逗号
复制代码


6.1.2、例子


   创建一张学生表(t_student) 有id、name、email、age。


CREATE TABLE t_student (
  id BIGINT,
  name VARCHAR(15),
  email VARCHAR(25),
  age INT
);
复制代码


6.1.3、注意


   创建表时,不能使用 MySQL 的关键字、保留字。


   解决办法:

# 1. 尽量避免使用关键字,可以使用其他的单词或单词组合来代替。
# 2. 一般情况下,创建表的时候习惯使用 t_ 做表名的开头。
# 3. 使用反引号(``) 将表名括起来就 ok  (`order`)。
复制代码


6.2、删除表


6.2.1、语法


DROP TABLE 表名;
复制代码


6.2.2、例子


-- 删除订单表
DROP TABLE `order`;
复制代码


6.2.3、注意


   如果表名是数据库的关键字或保留字需要加上反引号 (`)


6.3、表的复制和批量插入


6.3.1、表的复制


   表的复制本质上是将查询结果当做表创建出来。


create table 表名 as select语句;
复制代码


6.3.2、表的批量插入


   表的批量插入本质上是将查询结果插入到另一张表中。


insert into dept1 select * from dept;
复制代码


6.5、表的约束


   约束是为了保证表中的数据的合法性、有效性和完整性,我们一般对表会有约束。


  1. 非空约束:NOT NULL,不允许某列的内容为空。
  2. 设置列的默认值:DEFAULT。
  3. 唯一约束:UNIQUE,在该表中,该列的内容必须唯一。
  4. 主键约束:PRIMARY KEY, 非空且唯一。
  5. 主键自增长:AUTO_INCREMENT,从 1 开始,步长为 1。
  6. 外键约束:FOREIGN KEY,A表中的外键列. A表中的外键列的值必须参照于B表中的某一列(B表主 键)。


6.5.1、主键约束


   主键值是这行记录在这张表中的唯一标识,就如同身份证号。一张表的主键约束只能有一个。


主键约束(primary key)不能重复且不能为NULL。


6.5.1.1、主键的分类


  1. 业务主键:使用有业务含义的列作为主键 (不推荐使用);
  2. 自然主键:使用没有业务含义的列作为主键 (推荐使用);

6.5.1.2、如何设计主键


   对于主键,我们有以下两种的主键设计原则:


  1. 单字段主键,单列作为主键,建议使用。
  2. 复合主键,使用多列充当主键,不建议。


6.5.1.3、结论


   使用单字段的自然主键。


6.5.1.4、例子


   创建学生表,id为主键自增,name唯一,email不为空,age默认18。


-- 移除存在的表
DROP TABLE IF EXISTS `t_student`;
  CREATE TABLE t_student(
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(25) UNIQUE,
  email VARCHAR(25) NOT NULL,
  age INT DEFAULT 18
);
复制代码


6.5.2、外键约束(foreign key)


   **外键是另一张表的主键。**例如员工表与部门表之间就存在关联关系,其中员工表中的部门编号字段就是外键,是相对部门表的外键。


   外键可以为NULL,且不一定是另一张的主键,但是必须具有唯一性,一般情况下会引用另一张表的主键。


create table t_student(
  sno it,
    sname varchar(255),
    classno ,int
    foreign key (classno) references t_class(no) -- 对t_student的classno字段添加外键约束,引用的是t_calss的no字段
);
复制代码


6.5.3、唯一性约束(unique)


   唯一约束修饰的字段具有唯一性,不可以重复,但是可以为NULL,也可以同时为NULL。


create table t_user(
  id int,
    username varchar(255) unique,-- 列级约束
    pwd varchar(255)
)
复制代码

 

我们也可以同时给两个列或者多个列添加唯一约束。


-- 这样表示两个字段连起来不能重复,两个字段添加一个约束。表级约束
create table t_user(
  id,int,
    username varchar(255),
    pwd varchar(255),
    unique(username,pwd)
)
复制代码
-- 这样表示两个字段都不能重复,两个字段加两个约束。
create table t_user(
  id,int,
    username varchar(255) unique,
    pwd varchar(255) unique
)
复制代码


6.6、表与表之间的关系


6.6.1、一对一


   例如t_person表和t_card表,即人和身份证。这种情况需要找出主从关系,即谁是主表,谁是从表。人可以没有身份证,但身份证必须要有人才行,所以人是主表,而身份证是从表。设计从表可以有两种方案:


  1. 在t_card表中添加外键列(相对t_user表),并且给外键添加唯一约束;
  2. 给t_card表的主键添加外键约束(相对t_user表),即t_card表的主键也是外键。


6.6.2、一对多(多对一)


   一对多(多对一):最为常见的就是一对多!一对多和多对一,这是从哪个角度去看得出来的。t_user和t_section的关系,从t_user来看就是一对多,而从t_section的角度来看就是多对一!这种情况都是在多方创建外键!


6.6.3、多对多


   例如t_stu和t_teacher表,即一个学生可以有多个老师,而一个老师也可以有多个学生。这种情况通常需要创建中间表来处理多对多关系。例如再创建一张表t_stu_tea表,给出两个外键,一个相对t_stu表的外键,另一个相对t_teacher表的外键。


七、DML增删改操作


   DML是数据操作语句,用户对表的数据进行操作,所有的DML操作都有一个受影响的行,表示SQL执行,操作了多少行数据。


7.1、插入操作


7.1.1、语法


INSERT INTO 表名 (列1,列2,列3...) VALUES(值1,值2,值3...);
复制代码


7.1.2、例子


-- 1.插入完整数据记录
INSERT INTO t_student(name,email,age) VALUES('xiaoming','xiao@',18);
-- 2.插入数据记录一部分
INSERT INTO t_student(name,age) VALUES('xiaodong',19);
-- 3.插入多条数据记录(MySQL特有)
INSERT INTO t_student(name,email,age) VALUES('xiaohong','hong@',17),
('xiaohong2','hong2@',17),('xiaohong3','hong@3',17)
-- 4.插入查询结果
INSERT INTO t_student(name,email,age) SELECT name,email,age FROM t_student
复制代码


7.1.3、注意


   一次插入操作只插入一行,插入多条数据为 MySQL 特有语法(不推荐使用,Mybatis有循环来批量加入)


7.2、修改操作


7.2.1、语法


UPDATE 表名
SET 列1 = 值1, 列2 = 值2, column3 = value3...
WHERE [条件]
复制代码


7.2.2、练习


-- 将张三改为西门吹水
UPDATE t_student SET name='西门吹水' WHERE name='张三';
-- 将 id 为3 的 name 改为叶孤城,email 改为ye@,age 改为100
UPDATE t_student SET name='叶孤城' WHERE id=3;
复制代码

7.2.3、注意


  1. 如果省略了条件,那么整张表的数据都会被修改,所以一般都会带上条件
  2. 修改语句没有from关键字。


7.3、删除操作


7.3.1、语法


DELETE FROM 表名 WHERE [条件]
复制代码


7.3.2、练习


-- 删除 id 为 2 的学生信息
DELETE FROM t_student WHERE id=2;
-- 删除叶孤城的所有信息
DELETE FROM t_student WHERE name='叶孤城'
复制代码


7.3.3、注意


  1. FROM 不能写成 FORM
  2. 如果省略了 WHERE 子句,则全表的数据都会被删除


八、DQL 查询操作


8.1、语法说明


SELECT 列1,列2,列3... FROM 表名 [WHERE];
-- SELECT 选择要查询的列
-- FROM 提供数据源 (表、视图或其他的数据源)
-- 可以写*表示查询所有列,但是在实际开发中基本上不会使用,性能低,实际开发中是将所有字段列出来
复制代码


8.2、普通查询


8.2.1、设置别名


8.2.1.1、语法


SELECT 列名 AS 别名 FROM 表名 [WHERE];
SELECT 列名 别名 FROM 表名 [WHERE]
复制代码


8.2.1.2、作用


  1. 改变列的标题头。
  2. 作为计算结果的含义。
  3. 作为列的别名。
  4. 如果别名中使用特殊字符,或是强制大小写或有空格时都需要加单引号。


8.2.1.3、例子


-- 查询所有货品的id,名称,各进50个,并且每个运费1元的成本(使用别名)
SELECT id,productName,(costPrice + 1) * 50 1 AS allPrice FROM product
SELECT id,productName,(costPrice + 1) * 50 allPrice FROM product
复制代码


8.2.2、按照格式输出


   为方便用户浏览查询结果数据,有时需要设置查询结果的显示格式,可以使用 CONCAT 函数来 连接字符串。


8.2.2.1、语法


CONCAT(字符串1,字符串2,...)
复制代码


8.2.2.2、实战


-- 查询商品的名字和零售价。格式: xxx 商品的零售价为:ooo
SELECT CONCAT(productName,'商品的零售价为:',salePrice) FROM product
复制代码


8.2.3、消除重复的数据


   distinct前面不能接其他的字段,他只能出现在所有字段的最前方。他表示的意思是后面所有的字段联合起来一起去重。


SELECT DISTINCT 列名, ... FROM 表名;
复制代码


8.2.4、算数运算符


   对 number 型数据可以使用算数操作符创建表达式     他有如下优先级:


  1. 乘法和除法的优先级高于加法和减法。
  2. 同级运算的顺序是从左到右。
  3. 表达式中使用"括号"可强行改变优先级的运算顺序


-- 查询所有货品的id,名称和批发价(批发价=卖价*折扣)
SELECT id,productName,salePrice * cutoff FROM product
-- 查询所有货品的id,名称,和各进50个的成本价(成本=costPirce)
SELECT id,productName,costPrice * 50 FROM product
-- 查询所有货品的id,名称,各进50个,并且每个运费1元的成本
SELECT id,productName,(costPrice + 1) * 50 FROM product
复制代码


8.2.5、比较运算符


   比较运算符有如下几个:

  1. =
  2. >
  3. <
  4. <=
  5. != (<> 等价 !=)


-- 查询商品名为 罗技G9X 的货品信息
SELECT * FROM product WHERE productName='罗技G9X';
-- 查询零售价小于等于 200 的所有货品信息
SELECT * FROM product WHERE salePrice <= 200
-- 查询批发价大于 350 的货品信息
SELECT *,salePrice * cutoff allPrice FROM product WHERE salePrice * cutoff > 350
复制代码


8.2.6、逻辑运算符


运算符 含义
AND 如果组合的条件都是TRUE,返回TRUE
OR 如果组合的条件之一是TRUE,返回TRUE
NOT 如果下面的条件是FALSE,返回 TRUE,如果是 TRUE ,返回 FALSE


8.2.7、范围匹配


   范围匹配:BETWEEN AND 运算符,一般使用在数字类型的范围上。但对于字符数据和日期类型同样可

用。需要两个数据。


8.2.7.1、语法


WHERE 列名 BETWEEN minValue AND maxValue; -- 闭区间
复制代码


8.2.7.2、例子


-- 查询零售价在300-400 之间的货品信息
SELECT * FROM product WHERE salePrice BETWEEN 300 AND 400
-- 查询零售价不在300-400之间的货品信息
SELECT * FROM product WHERE NOT salePrice BETWEEN 300 AND 400
复制代码


8.2.8、集合查询


   集合查询: 使用 IN 运算符,判断列的值是否在指定的集合中。


8.2.8.1、语法


WHERE 列名 IN (值1,值2....);
复制代码


8.2.8.2、例子


-- 查询分类编号为2,4的所有货品的id,货品名称,
SELECT id,productName FROM product WHERE dir_id IN (2,4)
-- 查询分类编号不为2,4的所有货品的id,货品名称,
SELECT id,dir_id,productName FROM product WHERE dir_id NOT IN (2,4)
复制代码


8.2.9、判空


   IS NULL: 判断列的值是否为空值,非空字符串,空字符串使用==判断。


8.2.9.1、语法


WHERE 列名 IS NULL;
复制代码


8.2.9.2、例子


-- 查询商品名为NULL的所有商品信息。
SELECT * FROM product WHERE productName IS NULL;
SELECT * FROM product WHERE supplier =''
复制代码


8.2.9.3、注意


   使用=来判断只能判断空字符串,不能判断null 的,而使用IS NULL只能判断null值,不能判断空字符串。


8.2.10、过滤查询


   使用 WHERE 子句限定返回的记录


8.2.10.1、语法


SELECT <selectList>
FROM 表名
WHERE 条件;
复制代码


8.2.10.2、注意


  1. WHERE子句在 FROM 子句后。
  2. 查询语句的字句的执行顺序 FROM 子句: 从哪张表中去查询数据 => WHERE 子句 : 筛选需要哪些行的数据 => SELECT 子句: 筛选要显示的列。


8.2.11、模糊查询


   模糊查询数据使用 LIKE 运算符执行通配查询,他有两个通配符:


  1. %:表示可能有零个或者任意多个字符。
  2. _:表示任意的一个字符。


8.2.11.1、语法


WHERE 列名 Like '%M_'
复制代码


8.2.11.2、例子


-- 查询货品名称匹配'%罗技M9_' 的所有货品信息
SELECT * FROM product WHERE productName LIKE '%罗技M9_'
复制代码


8.3、结果排序


   使用 ORDER BY 子句将查询结果进行排序,他有两种排序的模式:


  1. ASC : 升序(默认)。
  2. DESC:降序。

   ORDER BY 子句出现在,SELECT 语句的最后。


8.3.1、例子


--单列排序: 选择id,货品名称,分类编号,零售价并且按零售价降序排序
SELECT id,productName,dir_id,salePrice FROM product ORDER BY salePrice DESC
--多列排序: 选择id,货品名称,分类编号,零售价先按分类编号降序排序,再按零售价升序排序
SELECT * FROM product ORDER BY dir_id DESC,salePrice ASC
复制代码


8.3.2、注意


  1. 谁在前面谁先排序。
  2. 如果列的别名使用 ' ' 则按此别名进行的排序无效。


-- 反例
SELECT id,salePrice 'sp' FROM product ORDER BY 'sp'
复制代码


8.4、分页查询


   limit是mysql特有的,他用于取结果集中的部分数据,Oracle中有一个相同的机制,叫rownum。


   limit是SQL语句最后执行的环节。


8.4.1、语法


SELECT <selectList>
FROM 表名
[WHERE] LIMIT ?,?
-- 第一个? : 开始行的索引数 beginIndex,默认为0
-- 第二个? : 每页显示的最大记录数 pageSize
-- 每页显示 3条数据
-- 第一页: SELECT * FROM product LIMIT 0,3
-- 第三页: SELECT * FROM product LIMIT 6,3
-- 第八页: SELECT * FROM product LIMIT 21,3
-- 当前页 : currentPage
-- 每页显示的最大记录数: pageSize
复制代码


8.4.2、通用的标准分页sql


   beginIndex = (currentPage - 1) * pageSize


8.4.3、案例


案例

   找出工资排名在4到6名的员工

select name,sal,from emp order by desc limit 3,6;
复制代码


8.5、分组函数


  • COUNT(*) : 统计表中有多少条记录
  • SUM(列) : 汇总列的总和
  • MAX(列) : 获取某一列的最大值
  • MIN(列) : 获取某一列的最小值
  • AVG(列) : 获取列的平均值

-- 查询货品表中有多少数据
SELECT COUNT(*) FROM product
-- 计算所有货品的总的进货价
SELECT SUM(costPrice) FROM product
复制代码


注意:

  1. 分组忽略null,无需额外过滤是否为null这个条件。**
  2. SQL语句中有一个语法规则,分组函数不可以直接使用在where字句当中。
  3. count(*)count(具体的字段的区别)
  • count(*)一定是总记录数,和字段无关。
  • count(具体的某个字段)是这个字段不为空的记录数。


8.6、分组查询


8.6.1、group by


group by:按照某个字段或者是某些字段进行分组。


   聚合函数分组会和group by一起联合使用,并且任何一个分组函数都是在group by语句执行结束之后才会执行。当一条sql语句没有group by的话,整张表的数据会自成一组。     SQL语句中有一个语法规则,分组函数不可以直接使用在where字句当中。原因是因为:group by是在where执行之后才会执行。如下面这条错误的sql语句:


select * from emp where sal > avg(sal);
复制代码

 

当执行到avg(sal)的时候,还没有执行group by,所以没办法执行分组函数。还没有分组就不可以执行分组函数。


需求:求每一个工作岗位的最高薪资

select max(sal),job from emp group by job;
复制代码


   结论:当一条sql语句中有group by的时候,select 后面只允许出现分组函数或者是参加分组的字段。


需求:找出每个部门不同工作岗位的最高薪资)

select
  deptno ,job ,max(sql)
from 
  emp
group by
  deptno,job
复制代码


8.6.2、having


   having:having是对分组之后的数据进行再次过滤。


需求:找出每个部门的平均薪资,要求显示薪资大于2000的数据

select val(sal),deptno from emp group by deptno having val(sal) > 2000;
复制代码


8.6.3、group by和having的总结


   能用where过滤的就先用where过滤,无法用where过滤的在用having,但是having一定要搭配group by使用,先分组在过滤。


8.6、DQL字句的执行顺序


select 
  ...
from 
  ...
where
  ...
group by
  ...
having
  ...
order by
  ...
limit
  ...
复制代码


  1. from: 从哪张表中去查数据。
  2. where: 筛选需要的行数据。
  3. group by :分组
  4. having:对分组的数据进行再次过滤
  5. SELECT : 筛选需要显示的列的数据。
  6. ORDER BY : 排序操作。


九、多表查询


9.1、连接查询


   在实际开发中,大部分的情况下都不是从单表中查询数据,一般是多张表进行联合查询取出最终的结果,一般一个业务都会对应多张表。


连接查询的分类有两种:

  1. SQL92(语法较老,过时)。
  2. SQL99(语法比较新)。


9.2、笛卡尔积现象


   当两张表进行连接查询的时候,没有任何条件进行限制,最终查询的结果条数是两张表记录条数的乘积,这个现象称为笛卡尔积现象。


   我们在开发的时候一般会给表起别名,他有两个好处:

  1. 执行效率高。
  2. 可读性好


select 
  e.ename,d.dname
from
  emp e,dept d
复制代码

 

这样出现的条数就是两张表条数的乘积。


   既然出现了笛卡尔积现象,我们就要避免笛卡尔积现象,避免笛卡尔积现象的措施就是增加条件进行过滤,但是避免了笛卡尔积你现象,会减少记录匹配的次数吗?答案是不会,次数还是两张表条数的乘积,只不过显示的是有效的记录数。


9.3、内连接


   假设A和B两张表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录都会被查询出来,AB两张表是平等的,没有主副之分,这就是内连接。


9.3.1、等值连接


   内连接最大的特点是:条件是等量关系。


select
  ...
from
  ...
inner join -- inner是可以省略的,带着inner可读性更好
  ...
on 
  连接条件
where
  ...
复制代码
select 
  e.name,d.name 
from 
  emp e 
inner join -- inner是可以省略的,带着inner可读性更好
  dept d 
on 
  e.deptno =  d.deptno
复制代码

 

SQL99语法结构更清晰一些,表的连接条件和后来的where过滤条件分离了。


9.3.2、非等值连接


   连接条件中的关系是非等量关系。


select e.name,e.sal,e.grade
from emp e
join salgrade s
on e.sal between s.local and s.hisal
复制代码


9.3.3、自连接


   最大的特点是一张表看成两张表,自己连接自己。(不常用)


9.4、外连接


   假设A表和B表进行连接,使用外连接的话,AB两张表有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表。


   当副表中的数据没有和主表中的数据匹配上的时候副表自动模拟出NULL与之匹配。主表的数据会无条件的全部查询出来。


9.4.1、外连接的分类


外连接分为两类:

  1. 左外连接(左连接 LEFT):表示左边的这张表是主表。
  2. 右外连接(右连接 RIGHT):表示右边的这张表是主表。


左连接有连接的写法,右连接也有对应的左连接的写法。用左连接LEFT的时候,说明上面(左边)的表是主表。


9.4.1.1、左连接


SELECT * FROM emp e LEFT OUTER JOINdept d ON e.deptno=d.deptno;
复制代码


注意:OUTER可以省略


   左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。


9.4.1.2、右连接


   右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。


需求:

 

 dept表中的40部门并不存在员工,但在右连接中,如果dept表为右表,那么还是会查出40部门,但相应的员工信息为NULL。


SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno
复制代码


9.4.2、注意


   内连接说明两张表是平等的,没有主副之分。

   外连接说明有一张表是主表,另一张表是副表。

   在开发中外连接居多,因为内连接查询的数据会丢失。


9.5、三张表连接


select ...
from
  ...
join
  ...
on
  ...
join
  ...
on
  ...(条件)
复制代码


9.6、union


   union关键字可以用于将查询结果集相加。他是连接两个查询结果的,可以用于两张不相干的表中的数据拼接在一起显示。


   注意:union必须用于两张列数相同的表进行查询,否则无法显示。


案例

 

  查询工作岗位是MANAGER和SALESMAN的员工


select ename,job from  emp where job = 'MANAGER'
union
select ename,job from  emp where job = 'SALESMAN'
复制代码


十、子查询


10.1、子查询概述


   select语句中嵌套select语句,被嵌套的select语句就是子查询,他可以出现的位置有select、from、where后。


10.2、where子句中使用


案例

 

 找出高于平均薪资的员工信息


select * 
from emp 
where sal > (select avg(sal) from emp);
复制代码


10.3、from字句后使用


案例

   

找出每个部门平均薪水的薪资等级。


  1. 先找出每个部门的平均薪水(按照部门编号分组,求sal的平均值)
select deptno,avg(sal) avgsal from emp group by deptno
复制代码


  1. 将以上的查询结果作为临时表t,让t表和salgrade(薪水等级表) s连接,条件是:t.avgsal between s.losal and s.hisal
select 
  t.*,s.grade
from
  (select deptno,avg(sal) avgsal from emp group by deptno) t
join
  salgrade s
on
  t.avgsal between s.losal and s.hisal
复制代码


10.4、在select后使用


需求

 

找出每个员工所在的部门名称,要求显示员工名和部门名。


select 
  e.ename,
  (select d.dname from dept d where e.deptno = d.deptno) dname
from 
  emp e;
复制代码


十一、事务


11.1、什么是事务


   一个事务是一个i完整的业务逻辑单元,不可再分。事务可以保证多个操作原子性,要么全成功,要么全失败。对于数据库来说事务保证批量的DML要么全成功,要么全失败。


和事务相关的语句只有DML语句,因为他们这三个语句都是和数据库表中的数据相关的。事务的存在是为了保证数据的完整性、安全性。


11.2、开启事务的原理


   假设我们完成一个操作,需要先执行一条insert,然后再执行一条update,最后执行一条delete,在mysql中执行流程可以这么理解:


11.JPG


11.3、事务的特征


   事务具有四个特征ACID


  1. 原子性(Atomicity)

   事务是最小的工作单元,不可再分。整个事务中的所有操作,必须作为一个单元全部完成(取消)。


  1. 一致性(Consistency)

   事务必须保证多条DML语句同时成功或者同时失败。


  1. 隔离性(Isolation)

   一个事务不会影响其他事务的运行。


  1. 持久性(Durability)

   最终该事务对数据库所作的更改将持久地保存在硬盘文件之中,事务才算成功。


    MySQL事务默认情况下是自动提交的,可以通过命令来改成手工提交。


start transaction;
复制代码


11.4、隔离性详解


11.4.1、并发访问可能导致的问题


####  11.4.1.1、脏读取
复制代码

 

一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交,这就出现了脏读取。


11.4.1.2、不可重复读


   在同一个事务中,同一个读操作对同一个数据的前后两次读取产生了不同的结果,这就是不可重复读。


11.4.1.3、幻读


   幻像读是指在同一个事务中以前没有的行,由于其他事务的提交而出现的新行。幻读强调的是前后读的行数不一样。


11.4.2、隔离级别


   InnoDB 实现了四个隔离级别,用以控制事务所做的修改,并将修改通告至其它并发的事务。隔离级别从低往高依次是:


  1. 读未提交(READ UMCOMMITTED)
  2. 读已提交(READ COMMITTED)
  3. 可重复读(REPEATABLE READ) MySQL默认
  4. 串行化(SERIALIZABLE)


12.JPG


11.4.2.1、读未提交


   对方的事务还没有提交,我们当前事务可以读取到对方未提交的数据。这种隔离级别是最低的,读为未提交存在脏读现象,表示堵到了脏数据。


11.4.2.2、读已提交


   对方事务提交之后的数据我们才可以读到,这种隔离级别解决了脏读现象,但是却出现了不可重复读现象。


   这个级别是oracle的默认隔离级别。


11.4.2.3、可重复读


   我们无法看到已提交的事务了,这种隔离级别虽然解决了不可重复读的问题,但是却带来了幻读的问题。比方说一个线程删除了数据库中的所有数据,但是我们依然读取的是原来的数据,读到的是数据库的备份。


MySQL的默认级别。


11.4.2.4、串行化


   将一个事务与其他事务完全地隔离。两个事务不可以并发,线程之间需要排队,也叫作序列化。虽然很安全,但是性能很低且客户的体验不好。


十二、索引


12.1、什么是索引


   索引相当于一本书的目录,通过目录可以快速找到对应的资源。索引被用来快速找出在一个列上用一特定值的行,索引可以有效地缩小扫描的范围。添加索引是给某个字段或者是某些字段添加的。


   在数据库方面,查询一张表的时候有两种检索方式:

  1. 全表扫描
  2. 根据索引检索(效率高)

 

索引虽然可以提高检索的效率,但是不能随意添加索引,因为索引也是数据库中的对象,也需要数据库不断地维护,维护需要成本的。比如表中的的数据如果经常被修改的话就不适合添加索引,因为数据一旦被修改,索引需要重新排序。


12.2、什么时候需要创建索引


  1. 数据量庞大。
  2. 该字段很少的DML操作(因为字段进行修改操作,索引也需要维护)。
  3. 该字段经常出现在where子句中(经常根据哪个字段查询)


注意:主键和具有unique约束的字段会自动添加索引,根据主键查询的效率高,尽量根据主键索引,我们可以查询sql语句的执行计划。他的底层是B+Tree。


explain select * from emp where SAL = 1500;
复制代码


   type字段的值时ALL表示是全表扫描(没有添加索引)。rows表示搜索了14条数据。


12.3、添加索引


-- 给emp表的sal字段添加一个索引,名称为emp_sal_index
create index emp_sal_index on emp(sal);
-- 语法格式
create index 索引名称 on 表名(字段名)
复制代码

13.JPG


12.4、查看索引


-- 查看索引的语法
show index from emp;
-- 语法格式
show index from 表名;
复制代码

14.JPG


12.5、删除索引


-- 删除索引的语法
drop index 索引名称 on 表名;
复制代码


12.6、索引的原理


   索引底层采用的数据结构是B+Tree,通过B+Tress缩小扫描范围,底层索引进行排序、分区,索引会携带在表中的物理地址,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位到表中的数据,效率是最高的(不走表,走硬盘)。


select ename from emp where ename = 'SMITH';
复制代码

通过索引sql语句会转换


select ename from emp where 物理地址 = '索引检索到的物理地址'
复制代码



12.7、索引的分类


  1. 单一索引:给打那个字段添加索引。
  2. 复合索引:给多个字段联合起来添加索引。
  3. 主键索引:主键上会自动添加索引。
  4. 唯一索引:有unique约束的字段上会自动添加索引。


12.8、索引的失效


   在模糊查询的时候,如果第一个通配符使用的是%,这个索引会失效,因为他不知道一开始匹配的字符是什么。


十三、视图


13.1、什么是视图


   视图是一种根据查询(也就是SELECT表达式)定义的数据库对象,用于获取想要看到和使用的局部数据。所以他也称为虚拟表。


   视图是站在不同的角度看到数据,同一张表的数据,通过不同的角度去看待数据。

   我们可以对视图进行增删改查,会影响到原表的数据,通过视图来影响原表数据的,并不是直接操作原表。只有DQL语句才可以以视图对象的方式创建出来。


15.JPG


13.2、创建视图


-- 语法格式
create view 视图名 as select语句
-- 示范
create view myview as select empo,ename from emp;
复制代码


13.3、修改视图


-- 语法格式
update 视图名 set 列名 = '值' where 条件;
复制代码


13.4、删除视图


-- 语法格式
delete from 视图名 where 条件;
-- 示范
delete from myview where empo = '12134';
复制代码


13.5、视图的作用


   视图可以隐藏表的实现细节,保密级别比较高的系统,数据库只对外提供相关的视图,面向视图对象进行CRUD。


十四、数据库设计三范式


   设计范式是设计表的依据,按照这三个范式设计的表不会出现数据冗余。但是在实际开发中,根据客户的需求,可能会拿数据冗余来换取执行速度,拿空间换时间。


14.1、第一范式


   任何一张表都应该有主键,且每一个字段原子性不可再分。


14.2、第二范式


   建立在第一范式的基础上,所有非主键字段完全依赖于主键,不能产生部分依赖。

典型的例子就是解决多对多的问题上,遇到多对多的时候,背口诀:多对多?三张表,关系表两外键


14.3、第三范式


   建立在第二范式的基础上,所有非主键字段直接依赖主键,不能产生传递依赖。

   典型的例子就是一对多,遇到一对多问题的时候背口诀:一对多?两张表,多的表加外键。


14.4、一对一关系的设计方案


14.4.1、主键共享


t_user_login 用户登录表

id(pk) username password
1 zs 123
2 ls 456

t_user_detail 用户详细信息表

id(pk+fk) realname tel
1 张三 111
2 李四 456


14.4.2、外键唯一


t_user_login 用户登录表

id(pk) username password
1 zs 123
2 ls 456

t_user_detail 用户详细信息表

id(pk) realname tel userid(fk+unique)
1 张三 111 2
2 李四 456 2


视图

-- 语法格式
delete from 视图名 where 条件;
-- 示范
delete from myview where empo = '12134';
复制代码


13.5、视图的作用


   视图可以隐藏表的实现细节,保密级别比较高的系统,数据库只对外提供相关的视图,面向视图对象进行CRUD。


十四、数据库设计三范式


   设计范式是设计表的依据,按照这三个范式设计的表不会出现数据冗余。但是在实际开发中,根据客户的需求,可能会拿数据冗余来换取执行速度,拿空间换时间。


14.1、第一范式


   任何一张表都应该有主键,且每一个字段原子性不可再分。


14.2、第二范式


   建立在第一范式的基础上,所有非主键字段完全依赖于主键,不能产生部分依赖。

   典型的例子就是解决多对多的问题上,遇到多对多的时候,背口诀:多对多?三张表,关系表两外键


14.3、第三范式


   建立在第二范式的基础上,所有非主键字段直接依赖主键,不能产生传递依赖。

   典型的例子就是一对多,遇到一对多问题的时候背口诀:一对多?两张表,多的表加外键。


14.4、一对一关系的设计方案


14.4.1、主键共享


t_user_login 用户登录表

id(pk) username password
1 zs 123
2 ls 456

t_user_detail 用户详细信息表

id(pk+fk) realname tel
1 张三 111
2 李四 456


14.4.2、外键唯一


t_user_login 用户登录表

id(pk) username password
1 zs 123
2 ls 456

t_user_detail 用户详细信息表

id(pk) realname tel userid(fk+unique)
1 张三 111 2
2 李四 456 2
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
关系型数据库 MySQL
【MySQL】——Select查询语句知识点练习(其一)
【MySQL】——Select查询语句知识点练习(其一)
|
6月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL LIKE 子句
总结 vue3 的一些知识点:MySQL LIKE 子句
|
6月前
|
安全 关系型数据库 MySQL
总结MySQL 的一些知识点:MySQL 排序(上)
总结MySQL 的一些知识点:MySQL 排序
|
6月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL NULL 值处理
总结 vue3 的一些知识点:MySQL NULL 值处理
|
6月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL 连接的使用
总结 vue3 的一些知识点:MySQL 连接的使用
|
关系型数据库 MySQL 数据库
关于mysql涉及到的知识点,C语言如何操作mysql
关于mysql涉及到的知识点,C语言如何操作mysql
|
存储 关系型数据库 MySQL
MySQL,其他部分知识点补充
MySQL,其他部分知识点补充
|
22天前
|
存储 Oracle 关系型数据库
[MySQL]知识点
本文详细介绍了MySQL中int族和char族数据类型的特点、存储范围及使用建议,以及text、blob类型和内置字符处理函数。文章强调了数据类型选择的重要性,并提供了多个实例帮助理解。
33 0
[MySQL]知识点
|
3月前
|
存储 关系型数据库 MySQL
mysql锁的知识点简述
了解和合理应用MySQL中的锁机制,对于设计高并发、高可用的数据库应用至关重要。在系统设计初期就要考量锁策略,根据实际使用场景灵活调整,以最小化锁竞争,提高事务处理速度。
57 0
|
5月前
|
SQL 关系型数据库 MySQL
Mysql从入门到精通——Mysql知识点总结(基础篇)
Mysql从入门到精通——Mysql知识点总结(基础篇)

热门文章

最新文章

下一篇
无影云桌面