8月29-31日上课内容 第五章 MySQL高级SQL语句

8月28日回顾

二进制日志中需要关注的部分

1、at:开始的位置点

2、end Log_pos:结束的位置

3、时间戳:2023-08-29 15:54:14

4、SQL语句

增量恢复
1、一般恢复

普通恢复

直接使用二进制文件进行恢复

2、断点恢复

基于位置点恢复

如果单独使用

--stop-poistion #之前所有数据进行恢复

--start-poistion#之后的所有数据进行恢复

组合使用
--start-poistion='1'        #开始

--stop-poistion             #结束   


3、时间点恢复

基于时间点恢复

如果单独使用
--stop-poistion

--start-poistion        之后的所有数据进之前所有数据进行恢复行恢复

组合使用
-start-poistion='2023-08-29 16:00:15'        #开始        --stop-poistion='2023-08-29 16:14:16 #结束   只恢复2023-08-29 16:00:15的数据到52023-08-29 16:14:16数据 结束

本章结构

一、MySQL进阶查询

常用查询
(增、删、改、查)
对 MySQL 数据库的查询,除了基本的查询外,有时候需要对查询的结果集进行处理。 例如只取 10 条数据、对查询结果进行排序或分组等等


1、按关键字排序


PS:类比于windows 任务管理器
使用 SELECT 语句可以将需要的数据从 MySQL 数据库中查询出来,如果对查询的结果进行排序,可以使用 ORDER BY 语句来对语句实现排序,并最终将排序后的结果返回给用户。这个语句的排序不光可以针对某一个字段,也可以针对多个字段

(1)语法

SELECT column1, column2, ... FROM table_name ORDER BY column1, column2, ... 

ASC|DESC;
ASC 是按照升序进行排序的,是默认的排序方式,即 ASC 可以省略。SELECT 语句中如果没有指定具体的排序方式,则默认按 ASC方式进行排序。
DESC 是按降序方式进 行排列。当然 ORDER BY 前面也可以使用 WHERE 子句对查询结果进一步过滤。

模板表:
数据库有一张info表,记录了学生的id,姓名,分数,地址和爱好
create table info (id int,name varchar(10) primary key not null ,score decimal(5,2),address varchar(20),hobbid int(5));

insert into ky29 values(1,'liuyi',80,'beijing',2);
insert into ky29 values(2,'wangwu',90,'shengzheng',2);
insert into ky29 values(3,'lisi',60,'shanghai',4);
insert into ky29 values(4,'tianqi',99,'hangzhou',5);
insert into ky29 values(5,'jiaoshou',98,'laowo',3);
insert into ky29 values(6,'hanmeimei',10,'nanjing',3);
insert into ky29 values(7,'lilei',11,'nanjing',5);

mysql> select * from info;
+------+-----------+-------+------------+--------+
| id   | name      | score | address    | hobbid |
+------+-----------+-------+------------+--------+
|    1 | liuyi     | 80.00 | beijing    |      2 |
|    2 | wangwu    | 90.00 | shengzheng |      2 |
|    3 | lisi      | 60.00 | shanghai   |      4 |
|    4 | tianqi    | 99.00 | hangzhou   |      5 |
|    5 | jiaoshou  | 98.00 | laowo      |      3 |
|    6 | hanmeimei | 10.00 | nanjing    |      3 |
+------+-----------+-------+------------+--------+

按分数排序,默认不指定是升序排列

mysql> select id,name,score from info order by score;
+-----------+-------+
| name      | score |
+-----------+-------+
| caicai    | 70.00 |
| shangzhen | 80.00 |
| zhaokun   | 80.00 |
| xiawenjie | 80.00 |
| chengu    | 88.00 |
| shidapeng | 90.00 |
| tangyan   | 98.00 |
+-----------+-------+
7 rows in set (0.01 sec)

分数按降序排列

mysql> select id,name,score from info order by score desc;
+-----------+-------+
| name      | score |
+-----------+-------+
| tangyan   | 98.00 |
| shidapeng | 90.00 |
| chengu    | 88.00 |
| shangzhen | 80.00 |
| zhaokun   | 80.00 |
| xiawenjie | 80.00 |
| caicai    | 70.00 |
+-----------+-------+
7 rows in set (0.01 sec)

order by还可以结合where进行条件过滤,筛选地址是杭州的学生按分数降序排列

mysql> select name,score from info where address='hangzhou' order by score desc;
+-----------+-------+
| name      | score |
+-----------+-------+
| zhaokun   | 80.00 |
| xiawenjie | 80.00 |
| caicai    | 70.00 |
+-----------+-------+
3 rows in set (0.00 sec)

ORDER BY 语句也可以使用多个字段来进行排序

当排序的第一个字段相同的记录有多条的情况下,这些多条的记录再按照第二个字段进行排序,ORDER BY 后面跟多个字段时,字段之间使用英文逗号隔开,优先级是按先后顺序而定
但order by 之后的第一个参数只有在出现相同值时,第二个字段才有意义

① 查询学生信息先按兴趣id降序排列,相同分数的,id也按降序排列

mysql> select id,name,hobbid from info order by hobbid desc,id desc;
+------+-----------+--------+
| id   | name      | hobbid |
+------+-----------+--------+
|    5 | lilei     |      5 |
|    4 | tianqi    |      5 |
|    3 | lisi      |      4 |
|    6 | hanmeimei |      3 |
|    5 | jiaoshou  |      3 |
|    2 | wangwu    |      2 |
|    1 | liuyi     |      2 |
+------+-----------+--------+
7 rows in set (0.00 sec)

②  查询学生信息先按兴趣id降序排列,相同分数的,id按升序排列

mysql> select id,name,hobbid from info order by hobbid desc,id;
+------+-----------+--------+
| id   | name      | hobbid |
+------+-----------+--------+
|    4 | tianqi    |      5 |
|    5 | lilei     |      5 |
|    3 | lisi      |      4 |
|    5 | jiaoshou  |      3 |
|    6 | hanmeimei |      3 |
|    1 | liuyi     |      2 |
|    2 | wangwu    |      2 |
+------+-----------+--------+
7 rows in set (0.00 sec)

2、区间判断及查询不重复记录

① AND/OR ——且/或

mysql> select * from info where score >70 and score <=90;
+------+--------+-------+------------+--------+
| id   | name   | score | address    | hobbid |
+------+--------+-------+------------+--------+
|    1 | liuyi  | 80.00 | beijing    |      2 |
|    2 | wangwu | 90.00 | shengzheng |      2 |
+------+--------+-------+------------+--------+
2 rows in set (0.00 sec)

mysql> select * from ky19 where score >70 or score <=90;

+------+-----------+-------+------------+--------+
| id   | name      | score | address    | hobbid |
+------+-----------+-------+------------+--------+
|    1 | liuyi     | 80.00 | beijing    |      2 |
|    2 | wangwu    | 90.00 | shengzheng |      2 |
|    3 | lisi      | 60.00 | shanghai   |      4 |
|    4 | tianqi    | 99.00 | hangzhou   |      5 |
|    5 | jiaoshou  | 98.00 | laowo      |      3 |
|    6 | hanmeimei | 10.00 | nanjing    |      3 |
|    5 | lilei     | 11.00 | nanjing    |      5 |
+------+-----------+-------+------------+--------+
7 rows in set (0.00 sec)

#嵌套/多条件


mysql> select * from info where score >70 or (score >75 and score <90);
+------+----------+-------+------------+--------+
| id   | name     | score | address    | hobbid |
+------+----------+-------+------------+--------+
|    1 | liuyi    | 80.00 | beijing    |      2 |
|    2 | wangwu   | 90.00 | shengzheng |      2 |
|    4 | tianqi   | 99.00 | hangzhou   |      5 |
|    5 | jiaoshou | 98.00 | laowo      |      3 |
+------+----------+-------+------------+--------+

添加:
② distinct 查询不重复记录


语法:

select distinct 字段 from 表名﹔
mysql> select distinct hobbid from info;
+--------+
| hobbid |
+--------+
|      2 |
|      4 |
|      5 |
|      3 |
+--------+

3、对结果进行分组

通过 SQL 查询出来的结果,还可以对其进行分组,使用 GROUP BY 语句来实现 ,GROUP BY 通常都是结合聚合函数一起使用的,常用的聚合函数包括:计数(COUNT)、 求和(SUM)、求平均数(AVG)、最大值(MAX)、最小值(MIN),GROUP BY 分组的时候可以按一个或多个字段对结果进行分组处理。

(1)语法

SELECT column_name, aggregate_function(column_name)FROM table_name WHERE column_name operator value GROUP BY column_name;

按hobbid相同的分组,计算相同分数的学生个数(基于name个数进行计数)

#以 
mysql> select count(name),hobbid from info group by hobbid;
+-------------+--------+
| count(name) | hobbid |
+-------------+--------+
|           2 |      2 |
|           2 |      3 |
|           1 |      4 |
|           2 |      5 |
+-------------+--------+


结合where语句,筛选分数大于等于80的分组,计算学生个数

mysql> select count(name),hobbid from info where score>=80 group by hobbid;
+-------------+--------+
| count(name) | hobbid |
+-------------+--------+
|           2 |      2 |
|           1 |      3 |
|           1 |      5 |
+-------------+--------+
3 rows in set (0.00 sec)

全班同学成绩表
count(name):计数
score 分数 :
score>=80 :优秀
score >=60 and score <80 :优-

结合order by把计算出的学生个数按升序排列

mysql> select count(name),score,hobbid from info where score>=80 group by hobbid order by count(name) asc;
+-------------+-------+--------+
| count(name) | score | hobbid |
+-------------+-------+--------+
|           1 | 99.00 |      5 |
|           1 | 98.00 |      3 |
|           2 | 80.00 |      2 |
+-------------+-------+--------+
3 rows in set (0.00 sec)

限制结果条目(limit⭐⭐⭐)

limit 限制输出的结果记录
在使用 MySQL SELECT 语句进行查询时,结果集返回的是所有匹配的记录(行)。有时候仅 需要返回第一行或者前几行,这时候就需要用到 LIMIT 子句

(1)语法
SELECT column1, column2, ... FROM table_name LIMIT [offset,] number

LIMIT 的第一个参数是位置偏移量(可选参数),是设置 MySQL 从哪一行开始显示。 如果不设定第一个参数,将会从表中的第一条记录开始显示。需要注意的是,第一条记录的 位置偏移量是 0,第二条是 1,以此类推。第二个参数是设置返回记录行的最大数目。

查询所有信息显示前4行记录

mysql> select * from info limit 3;
+----+-----------+-------+----------+-------+
| id | name      | score | address  | hobby |
+----+-----------+-------+----------+-------+
|  1 | shidapeng | 90.00 | nanjing  |  NULL |
|  2 | shangzhen | 80.00 | beijing  |  NULL |
|  3 | tangyan   | 98.00 | shanghai |  NULL |
+----+-----------+-------+----------+-------+
3 rows in set (0.00 sec)

从第4行开始,往后显示3行内容

mysql> select * from info limit 3,3;
+----+---------+-------+----------+-------+
| id | name    | score | address  | hobby |
+----+---------+-------+----------+-------+
|  6 | chengu  | 88.00 | nanjing  |  NULL |
|  7 | caicai  | 70.00 | hangzhou |  NULL |
|  8 | zhaokun | 80.00 | hangzhou |  NULL |
+----+---------+-------+----------+-------+
3 rows in set (0.00 sec)

结合order by语句,按id的大小升序排列显示前三行

mysql> select id,name from info order by id limit 3;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | shidapeng |
|  2 | shangzhen |
|  3 | tangyan   |
+----+-----------+
3 rows in set (0.00 sec)

#基础select 小的升阶 怎么输出最后三行⭐⭐

mysql> select id,name from info order by id desc limit 3;
+------+-----------+
| id   | name      |
+------+-----------+
|    7 | lilei     |
|    6 | hanmeimei |
|    5 | jiaoshou  |
+------+-----------+
3 rows in set (0.00 sec)

输出前三行,怎么输出 : limit 3
limit 2 您说的是前三行,limit 是做为位置偏移量的定义,他的起始是从0开始,而0表示的是字段

看降序的4和3行

如果不知道是哪一行可以先降序,再限制

29日小结

1、按关键字排序

ORDER BY 语句用来实现排序的         ASC是按照升序排序是默认的排序方式

DESC 是按降序进行排列 ,当然ORDER BY 前面可以使用 where字句查询结果进一步过滤


2、区间判断查询    不重复记录

and/or  ---且/或        distinct查询不重复记录

3、对结果进行分组
查询sql结果     对结果进行分组 GROUP BY来实现     group by通常都是结合聚合函数一起使用

聚合函数: count(计数)        sum (求和)        avg (平均数)        max(最大值)         min(最小值)

4、限制结果条目

limit 限制输出记过记录

4、设置别名(alias ——> as)


在 MySQL 查询时,当表的名字比较长或者表内某些字段比较长时,为了方便书写或者 多次使用相同的表,可以给字段列或表设置别名。使用的时候直接使用别名,简洁明了,增强可读性

(1)语法

对于列的别名:SELECT column_name AS alias_name FROM table_name;


对于表的别名:SELECT column_name(s) FROM table_name AS alias_name;

在使用 AS 后,可以用 alias_name 代替 table_name,其中 AS 语句是可选的。AS 之后的别名,主要是为表内的列或者表提供临时的名称,在查询过程中使用,库内实际的表名 或字段名是不会被改变的

列别名设置示例:
select name as 姓名,score as 成绩 from info;    

如果表的长度比较长,可以使用 AS 给表设置别名,在查询的过程中直接使用别名
临时设置info的别名为i
select i.name as 姓名,i.score as 成绩 from info as i;

查询info表的字段数量,以number显示
mysql> select count(*) as number from info;
+--------+
| number |
+--------+
|      7 |
+--------+
1 row in set (0.00 sec)

不用as也可以,一样显示

mysql> select count(*) number from info;
+--------+
| number |
+--------+
|      7 |
+--------+
1 row in set (0.00 sec)

使用场景:


1、对复杂的表进行查询的时候,别名可以缩短查询语句的长度
2、多表相连查询的时候(通俗易懂、减短sql语句)

此外,AS 还可以作为连接语句的操作符。
创建t1表,将info表的查询记录全部插入t1表


mysql> create table t1 as select * from info;
Query OK, 7 rows affected (0.02 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+----+-----------+-------+----------+-------+
| id | name      | score | address  | hobby |
+----+-----------+-------+----------+-------+
|  1 | shidapeng | 90.00 | nanjing  |  NULL |
|  2 | shangzhen | 80.00 | beijing  |  NULL |
|  3 | tangyan   | 98.00 | shanghai |  NULL |
|  6 | chengu    | 88.00 | nanjing  |  NULL |
|  7 | caicai    | 70.00 | hangzhou |  NULL |
|  8 | zhaokun   | 80.00 | hangzhou |  NULL |
|  9 | xiawenjie | 80.00 | hangzhou |  NULL |
+----+-----------+-------+----------+-------+
7 rows in set (0.00 sec)

两表区别:

#此处AS起到的作用:
1、创建了一个新表t1 并定义表结构,插入表数据(与info表相同)
2、但是”约束“没有被完全”复制“过来 #但是如果原表设置了主键,那么附表的:default字段会默认设置一个0

相似:
克隆、复制表结构
create table t1 (select * from info);
#也可以加入where 语句判断
create table test1 as select * from info where score >=60;
 

克隆、复制表结构

where语句判断

注意:在为表设置别名时,要保证别名不能与数据库中的其他表的名称冲突。
列的别名是在结果中有显示的,而表的别名在结果中没有显示,只在执行查询时使用。

5、通配符


通配符主要用于替换字符串中的部分字符,通过部分字符的匹配将相关结果查询出来。

通常通配符都是跟 LIKE 一起使用的,并协同 WHERE 子句共同来完成查询任务。

常用的通配符有两个,分别是:

%:百分号表示零个、一个或多个字符        *
_:下划线表示单个字符                     .

需求:查询名字是c开头的记录

mysql> select id,name from info where name like 'c%';
+----+--------+
| id | name   |
+----+--------+
|  7 | caicai |
|  6 | chengu |
+----+--------+
2 rows in set (0.00 sec)

查询名字里是c和i中间有一个字符的记录

mysql> select id,name from info where name like 'c_ic_i';
+----+--------+
| id | name   |
+----+--------+
|  7 | caicai |
+----+--------+
1 row in set (0.00 sec)

查询名字中间有g的记录

mysql> select id,name from info where name like '%g%';
+----+-----------+
| id | name      |
+----+-----------+
|  6 | chengu    |
|  2 | shangzhen |
|  1 | shidapeng |
|  3 | tangyan   |
+----+-----------+
4 rows in set (0.00 sec)

查询tang后面3个字符的名字记录

mysql> select id,name from info where name like 'tang___';
+----+---------+
| id | name    |
+----+---------+
|  3 | tangyan |
+----+---------+
1 row in set (0.00 sec)

通配符“%”和“_”不仅可以单独使用,也可以组合使用
查询名字以s开头的记录

mysql> select id,name from info where name like 's%_';
+----+-----------+
| id | name      |
+----+-----------+
|  2 | shangzhen |
|  1 | shidapeng |
+----+-----------+
2 rows in set (0.00 sec)

6、子查询

子查询的概念


子查询也被称作内查询或者嵌套查询,是指在一个查询语句里面还嵌套着另一个查询语 句。子查询语句是先于主查询语句被执行的,其结果作为外层的条件返回给主查询进行下一 步的查询过滤。
PS: 子语句可以与主语句所查询的表相同,也可以是不同表

select name,score from info where id in (select id from info where score >80);


以上同表示例:
主语句:select name,score from info where id
子语句(集合): select id from info where score >80

PS:子语句中的sql语句是为了,最后过滤出一个结果集,用于主语句的判断条件
 

⭐⭐ in: 将主表和子表关联/连接的语法

不同表/多表示例:


mysql> create table ky30(id int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into ky30 values(1),(2),(3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0


#多表查询


mysql> select id,name,score from info where id in (select * from ky30);
+------+--------+-------+
| id   | name   | score |
+------+--------+-------+
|    1 | liuyi  | 80.00 |
|    2 | wangwu | 90.00 |
|    3 | lisi   | 60.00 |
+------+--------+-------+
3 rows in set (0.00 sec)

子查询不仅可以在 SELECT 语句中使用,在 INERT、UPDATE、DELETE 中也同样适用。在嵌套的时候,子查询内部还可以再次嵌套新的子查询,也就是说可以多层嵌套。

子查询支持多层嵌套

(1)语法


IN 用来判断某个值是否在给定的结果集中,通常结合子查询来使用

语法:
<表达式> [NOT] IN <子查询>

当表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返回 FALSE。 若启用了 NOT 关键字,则返回值相反。需要注意的是,子查询只能返回一列数据,如果需 求比较复杂,一列解决不了问题,可以使用多层嵌套的方式来应对。 多数情况下,子查询都是与 SELECT 语句一起使用的

查询分数大于80的记录

mysql> select name,score from info where id in (select id from info where score>80);
+----------+-------+
| name     | score |
+----------+-------+
| wangwu   | 90.00 |
| tianqi   | 99.00 |
| jiaoshou | 98.00 |
| lilei    | 11.00 |
+----------+-------+
4 rows in set (0.01 sec)

子查询还可以用在 INSERT 语句中。子查询的结果集可以通过 INSERT 语句插入到其 他的表中

将t1里的记录全部删除,重新插入info表的记录

mysql> insert into t1 select * from info where id in (select id from info);
Query OK, 7 rows affected (0.00 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> select * from t1;                                                  
+----+-----------+-------+----------+-------+
| id | name      | score | address  | hobby |
+----+-----------+-------+----------+-------+
|  1 | shidapeng | 90.00 | nanjing  |  NULL |
|  2 | shangzhen | 80.00 | beijing  |  NULL |
|  3 | tangyan   | 98.00 | shanghai |  NULL |
|  6 | chengu    | 88.00 | nanjing  |  NULL |
|  7 | caicai    | 70.00 | hangzhou |  NULL |
|  8 | zhaokun   | 80.00 | hangzhou |  NULL |
|  9 | xiawenjie | 80.00 | hangzhou |  NULL |
+----+-----------+-------+----------+-------+
7 rows in set (0.00 sec)

UPDATE 语句也可以使用子查询。UPDATE 内的子查询,在 set 更新内容时,可以是单独的一列,也可以是多列。

将caicai的分数改为50

mysql> update info set score=50 where id in (select * from ky30 where id=2);
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from info;
+------+-----------+-------+------------+--------+
| id   | name      | score | address    | hobbid |
+------+-----------+-------+------------+--------+
|    1 | liuyi     | 80.00 | beijing    |      2 |
|    2 | wangwu    | 50.00 | shengzheng |      2 |
|    3 | lisi      | 60.00 | shanghai   |      4 |
|    4 | tianqi    | 99.00 | hangzhou   |      5 |
|    5 | jiaoshou  | 98.00 | laowo      |      3 |
|    6 | hanmeimei | 10.00 | nanjing    |      3 |
|    5 | lilei     | 11.00 | nanjing    |      5 |
+------+-----------+-------+------------+--------+
7 rows in set (0.00 sec)

update info set score=100 where id not in (select * from member where id >1);
表示 先匹配出member表内的id字段为基础匹配的结果集(2,3)
然后再执行主语句,以主语句的id 为基础 进行where 条件判断/过滤

DELETE 也适用于子查询

删除分数大于80的记录

mysql> delete from info where id in (select id where score>80);
Query OK, 3 rows affected (0.00 sec)

mysql> select id,name,score from t1;
+----+-----------+-------+
| id | name      | score |
+----+-----------+-------+
|  2 | shangzhen | 80.00 |
|  7 | caicai    | 50.00 |
|  8 | zhaokun   | 80.00 |
|  9 | xiawenjie | 80.00 |
+----+-----------+-------+
4 rows in set (0.00 sec)

在 IN 前面还可以添加 NOT,其作用与IN相反,表示否定(即不在子查询的结果集里面)


删除分数不是大于等于80的记录

mysql> delete from t1 where id not in (select id where score>=80);
Query OK, 1 row affected (0.00 sec)

mysql> select id,name,score from t1;
+----+-----------+-------+
| id | name      | score |
+----+-----------+-------+
|  2 | shangzhen | 80.00 |
|  8 | zhaokun   | 80.00 |
|  9 | xiawenjie | 80.00 |
+----+-----------+-------+
3 rows in set (0.00 sec)

EXISTS 这个关键字在子查询时,主要用于判断子查询的结果集是否为空。如果不为空, 则返回 TRUE;反之,则返回 FALSE

查询如果存在分数等于80的记录则计算info的字段数

mysql> select count(*) from info where exists(select id from info where score=80);
学校里面 (人员信息统计,只有当所有人全部签到之后,在人员信息统计表录入完成侯,我才需要进行统计)
+----------+
| count(*) |
+----------+
|        7 |
+----------+
1 row in set (0.00 sec)

查询如果存在分数小于50的记录则计算info的字段数,info表没有小于50的,所以返回0

mysql> select count(*) from info where exists(select id from info where score<50);
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

子查询,别名as
#查询info表id,name 字段
select id,name from info;
以上命令可以查看到info表的内容

#将结果集做为一张表进行查询的时候,我们也需要用到别名

示例:
需求:从info表中的id和name字段的内容做为"内容" 输出id的部分

mysql> select id from (select id,name from info);
ERROR 1248 (42000): Every derived table must have its own alias
#此时会报错,原因为:
select * from 表名 此为标准格式,而以上的查询语句,"表名"的位置其实是一个完整结果集,mysql并不能直接识别,而此时给与结果集设置一个别名,以”select a.id from a“的方式查询将此结果集视为一张"表",就可以正常查询数据了,如下:
select a.id from (select id,name from info) a;
相当于
select info.id,name from info;
select 表.字段,字段 from 表;

小结

5、设置别名
mysql查询的时候 表和字段做一个别名原因表和列的字段比较长

As 起到作用

创建表的时候 插入表的数据

可以克降表的数据和表结构 但是约束没有完全复制过来 附表


6、通配符

应用场景 快速查找数据库中内容

% 百分号表示零个或者一个或多个字符

_  下划线表示单个字符

7、子查询
子查询 就是 内查询或者嵌套查询 ,是指在一个查询语句里面还嵌套这另一个查询语句

子查询 模式 优先于主查询 可以在相同表和不同表之前进行查询

in 将主表和子表进行关联/连接

语法        in 用来判断某个值是否在给定结果集中

               in 通常结合子查询来进行使用

not in 取反

inser

update

delete

exists

判断         如果是否为空 ,如果不为空        则返回 true        否则反之 false

MySQL视图

视图的概念

视图:优化操作+安全方案  ⭐⭐
数据库中的虚拟表,这张虚拟表中不包含真实数据,只是做了真实数据的映射
视图可以理解为镜花水月/倒影,动态保存结果集(数据)
基础表info (7行记录) ——》映射(投影)--视图

作用场景[图]:
针对不同的人(权限身份),提供不同结果集的“表”(以表格的形式展示)

作用范围:

select * from info;            #展示的部分是info表
select * from view_name;    #展示的一张或多张表

功能:

简化查询结果集、灵活查询、可以针对不同用户呈现不同结果集、相对有更高的安全性
本质而言视图是一种select(结果集的呈现)

PS:视图适合于多表连接浏览时使用!不适合增、删、改
而存储过程适合于使用较频繁的SQL语句,这样可以提高执行效率!

##视图和表的区别和联系

#区别:

①、视图是已经编译好的sql语句。而表不是

②、视图没有实际的物理记录。而表有。
show table status\G

③、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表可以及时对它进行修改,但视图只能有创建的语句来修改

④、视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图可以不给用户接触数据表,从而不知道表结构。

⑤、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。

⑥、视图的建立和删除只影响视图本身,不影响对应的基本表。(但是更新视图数据,是会影响到基本表的)

#联系:

视图(view)是在基本表之上建立的表,它的结构(即所定义的列)和内容(即所有数据行)都来自基本表,它依据基本表存在而存在。一个视图可以对应一个基本表,也可以对应多个基本表。视图是基本表的抽象和在逻辑意义上建立的新关系。

示例:
需求:满足80分的学生展示在视图中

PS:这个结果会动态变化,同时可以给不同的人群(例如权限范围)展示不同的视图

#创建视图(单表)

mysql> create view v_score as select * from ky29 where score>=80;
Query OK, 0 rows affected (0.01 sec)

#查看表状态

show table status\G

#查看视图

mysql> select * from v_score;
+------+-----------+--------+----------+--------+
| id   | name      | score  | address  | hobbid |
+------+-----------+--------+----------+--------+
|    1 | liuyi     | 100.00 | beijing  |      2 |
|    4 | tianqi    | 100.00 | hangzhou |      5 |
|    5 | jiaoshou  | 100.00 | laowo    |      3 |
|    6 | hanmeimei | 100.00 | nanjing  |      3 |
|    7 | lilei     | 100.00 | nanjing  |      5 |
+------+-----------+--------+----------+--------+

#查看视图与源表结构

mysql> desc v_score;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | YES  |     | NULL    |       |
| name    | varchar(10)  | NO   |     | NULL    |       |
| score   | decimal(5,2) | YES  |     | NULL    |       |
| address | varchar(20)  | YES  |     | NULL    |       |
| hobbid  | int(5)       | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
5 rows in set (0.01 sec)

mysql> desc ky29;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | YES  |     | NULL    |       |
| name    | varchar(10)  | NO   | PRI | NULL    |       |
| score   | decimal(5,2) | YES  |     | NULL    |       |
| address | varchar(20)  | YES  |     | NULL    |       |
| hobbid  | int(5)       | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

#多表创建视图

创建test01表
create table test01 (id int,name varchar(10),age char(10));
insert into test01 values(1,'zhangsan',20);
insert into test01 values(2,'lisi',30);
insert into test01 values(3,'wangwu',29);

需求:需要创建一个视图,需要输出id、学生姓名、分数以及年龄

mysql> create view v_info(id,name,score,age) as select info.id,info.name,info.score,test01.age from info,test01 where info.name=test01.name;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from v_info;
+------+--------+-------+------+
| id   | name   | score | age  |
+------+--------+-------+------+
|    3 | lisi   | 60.00 | 30   |
|    2 | wangwu | 90.00 | 29   |
+------+--------+-------+------+
2 rows in set (0.00 sec)

#修改原表数据

mysql> update info set score='60' where name='liuyi';
Query OK, 1 row affected (1.62 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#查看视图

mysql> select * from v_score;
+------+-----------+--------+----------+--------+
| id   | name      | score  | address  | hobbid |
+------+-----------+--------+----------+--------+
|    4 | tianqi    | 100.00 | hangzhou |      5 |
|    5 | jiaoshou  | 100.00 | laowo    |      3 |
|    6 | hanmeimei | 100.00 | nanjing  |      3 |
|    7 | lilei     | 100.00 | nanjing  |      5 |
+------+-----------+--------+----------+--------+
4 rows in set (0.00 sec)

#同时可以通过视图修改原表

mysql> update v_score set score='120' where name='tianqi';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from v_score;
+------+-----------+--------+----------+--------+
| id   | name      | score  | address  | hobbid |
+------+-----------+--------+----------+--------+
|    4 | tianqi    | 120.00 | hangzhou |      5 |
|    5 | jiaoshou  | 100.00 | laowo    |      3 |
|    6 | hanmeimei | 100.00 | nanjing  |      3 |
|    7 | lilei     | 100.00 | nanjing  |      5 |
+------+-----------+--------+----------+--------+
4 rows in set (0.00 sec)

mysql> select * from info;
+------+-----------+--------+------------+--------+
| id   | name      | score  | address    | hobbid |
+------+-----------+--------+------------+--------+
|    1 | liuyi     |  60.00 | beijing    |      2 |
|    2 | wangwu    |  50.00 | shengzheng |      2 |
|    3 | lisi      |  50.00 | shanghai   |      4 |
|    4 | tianqi    | 120.00 | hangzhou   |      5 |
|    5 | jiaoshou  | 100.00 | laowo      |      3 |
|    6 | hanmeimei | 100.00 | nanjing    |      3 |
|    7 | lilei     | 100.00 | nanjing    |      5 |
+------+-----------+--------+------------+--------+
7 rows in set (0.00 sec)

修改表不能修改以函数、复合函数方式计算出来的字段
查询方便、安全性
查询方便:索引速度快、同时可以多表查询更为迅速(视图不保存真实数据,视图本质类似select)
安全性:我们实现登陆的账户是root ——》所拥有权限 ,视图无法显示完整的约束

---------------------------------------------------------------------------------------------------------------------------------

7、NULL值

在 SQL 语句使用过程中,经常会碰到 NULL 这几个字符。通常使用 NULL 来表示缺失的值,也就是在表中该字段是没有值的。如果在创建表时,限制某些字段不为空,则可以使用 NOT NULI关键字,不使用则默认可以为空。在向表内插入记录或者更新记录时,如果该字段没有 NOT NULL并且没有值,这时候新记录的该字段将被保存为 NULL。需要注意 的是,NULL 值与数字 0或者空白 (spaces)的字段是不同的,值为 NULL 的字段是没有 值的。在 SQL 语句中,使用 IS NULL可以判断表内的某个字段是不是 NULL 值,相反的用 IS NOT NULL 可以判断不是 NULL 值。


查询info表结构,name字段是不允许空值的


null值与空值的区别(空气与真空)

空值长度为0,不占空间,NULL值的长度为nul1,占用空间

is nul1无法判断空值

空值使用"="或者"<>"来处理 (! =)

count () 计算时,NULL会忽略,空值会加入计算

查看空值是否占用空间:

mysql> desc info;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(3)       | NO   | PRI | NULL    | auto_increment |
| name    | varchar(10)  | NO   | UNI | NULL    |                |
| score   | decimal(5,2) | YES  |     | NULL    |                |
| address | varchar(50)  | YES  |     | 未知    |                |
| hobbid  | int(3)       | YES  |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

插入一条记录,分数字段输入null,显示出来就是null

#验证:
alter table info add column addr varchar(50);

update info set addr='nj' where score >=70;

这就说明null在数据里面虽然占用空间,但是不统计在数据的长度里面

#统计数量:检测null是否会加入统计中

select count(addr) from info;

#将info表中其中一条数据修改为空值''
update info set addr='' where name='wangwu';

#统计数量,检测空值是不会被添加到统计中
select count(addr) from info;

#查询null值
mysql> select * from info where addr is NULL;
+------+-----------+-------+---------+--------+------+
| id   | name      | score | address | hobbid | addr |
+------+-----------+-------+---------+--------+------+
|    6 | hanmeimei | 10.00 | nanjing |      3 | NULL |
|    7 | lilei     | 11.00 | nanjing |      5 | NULL |
+------+-----------+-------+---------+--------+------+
2 rows in set (0.00 sec)


#查询不为空的值
ysql> select * from info where addr is not null;
+------+----------+-------+------------+--------+------+
| id   | name     | score | address    | hobbid | addr |
+------+----------+-------+------------+--------+------+
|    1 | liuyi    | 80.00 | beijing    |      2 | nj   |
|    2 | wangwu   | 90.00 | shengzheng |      2 | nj   |
|    3 | lisi     | 60.00 | shanghai   |      4 |      |
|    4 | tianqi   | 99.00 | hangzhou   |      5 | nj   |
|    5 | jiaoshou | 98.00 | laowo      |      3 | nj   |
|    1 | xiaoer   | 80.00 | hangzhou   |      3 | nj   |
+------+----------+-------+------------+--------+------+
6 rows in set (0.00 sec)

内连接   左连接  右连接

8、连接查询⭐⭐⭐(重点)

MySQL 的连接查询,通常都是将来自两个或多个表的记录行结合起来,基于这些表之间的 共同字段,进行数据的拼接。首先,要确定一个主表作为结果集,然后将其他表的行有选择 性的连接到选定的主表结果集上。使用较多的连接查询包括:内连接、左连接和右连接

内连接左连接和右连接图示

内连接图例

左连接图例

右连接同理

模板:
create table test1 (
a_id int(11) default null,
a_name varchar(32) default null,
a_level int(11) default null);

create table test2 (
b_id int(11) default null,
b_name varchar(32) default null,
b_level int(11) default null);

insert into test1 values (1,'aaaa',10);
insert into test1 values (2,'bbbb',20);
insert into test1 values (3,'cccc',30);
insert into test1 values (4,'dddd',40);

insert into test2 values (2,'bbbb',20);
insert into test2 values (3,'cccc',30);
insert into test2 values (5,'eeee',50);
insert into test2 values (6,'ffff',60);

1、内连接

概念

MySQL 中的内连接就是两张或多张表中同时符合某种条件的数据记录的组合。通常在 FROM 子句中使用关键字 INNER JOIN 来连接多张表,并使用 ON 子句设置连接条件,内连接是系统默认的表连接,所以在 FROM 子句后可以省略 INNER 关键字,只使用 关键字 JOIN。同时有多个表时,也可以连续使用 INNER JOIN 来实现多表的内连接,不过为了更好的性能,建议最好不要超过三个表

(1)语法

SELECT column_name(s)FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name;

模板表:
create table infos(name varchar(40),score decimal(4,2),address varchar(40));

insert into infos values('wangwu',80,'beijing'),('zhangsan',99,'shanghai'),('lisi',100,'nanjing');

实例

mysql> select * from infos;
+----------+-------+----------+
| name     | score | address  |
+----------+-------+----------+
| wangwu   | 80.00 | beijing  |
| zhangsan | 99.00 | shanghai |
| lisi     | 99.99 | nanjing  |
+----------+-------+----------+


mysql> select info.id,info.name from info inner join infos on info.name=infos.name;
+------+--------+
| id   | name   |
+------+--------+
|    2 | wangwu |
|    3 | lisi   |
+------+--------+
2 rows in set (0.00 sec)

内连查询:通过inner join 的方式将两张表指定的相同字段的记录行输出出来
内连查询:面试,直接了当的说 用inner join 就可以

2、左连接

概念

左连接也可以被称为左外连接,在 FROM 子句中使用 LEFT JOIN 或者 LEFT OUTER JOIN 关键字来表示。左连接以左侧表为基础表,接收左表的所有行,并用这些行与右侧参 考表中的记录进行匹配,也就是说匹配左表中的所有行以及右表中符合条件的行。

实例

mysql>  select * from info left join infos on info.name=infos.name;
+------+-----------+--------+------------+--------+------+--------+-------+---------+
| id   | name      | score  | address    | hobbid | addr | name   | score | address |
+------+-----------+--------+------------+--------+------+--------+-------+---------+
|    2 | wangwu    |  50.00 | shengzheng |      2 | nj   | wangwu | 80.00 | beijing |
|    3 | lisi      |  50.00 | shanghai   |      4 | nj   | lisi   | 99.99 | nanjing |
|    1 | liuyi     |  60.00 | beijing    |      2 | nj   | NULL   |  NULL | NULL    |
|    4 | tianqi    | 100.00 | hangzhou   |      5 |      | NULL   |  NULL | NULL    |
|    5 | jiaoshou  | 100.00 | laowo      |      3 | NULL | NULL   |  NULL | NULL    |
|    6 | hanmeimei | 100.00 | nanjing    |      3 | NULL | NULL   |  NULL | NULL    |
|    7 | lilei     | 100.00 | nanjing    |      5 | NULL | NULL   |  NULL | NULL    |
|    7 | lilei     | 100.00 | nanjing    |      5 | NULL | NULL   |  NULL | NULL    |
|    8 | abn       |  81.00 | bj         |      1 | nj   | NULL   |  NULL | NULL    |
+------+-----------+--------+------------+--------+------+--------+-------+---------+

左连接中左表的记录将会全部表示出来,而右表只会显示符合搜索条件的记录,右表记录不足的地方均为 NULL。

3、右连接

概念

右连接也被称为右外连接,在 FROM 子句中使用 RIGHT JOIN 或者 RIGHT OUTER JOIN 关键字来表示。右连接跟左连接正好相反,它是以右表为基础表,用于接收右表中的所有行,并用这些记录与左表中的行进行匹配

实例

mysql> select * from info right join infos on info.name=infos.name;
+------+--------+-------+------------+--------+------+----------+-------+----------+
| id   | name   | score | address    | hobbid | addr | name     | score | address  |
+------+--------+-------+------------+--------+------+----------+-------+----------+
|    2 | wangwu | 50.00 | shengzheng |      2 | nj   | wangwu   | 80.00 | beijing  |
| NULL | NULL   |  NULL | NULL       |   NULL | NULL | zhangsan | 99.00 | shanghai |
|    3 | lisi   | 50.00 | shanghai   |      4 | nj   | lisi     | 99.99 | nanjing  |
+------+--------+-------+------------+--------+------+----------+-------+----------+
3 rows in set (0.00 sec)

在右连接的查询结果集中,除了符合匹配规则的行外,还包括右表中有但是左表中不匹 配的行,这些记录在左表中以 NULL 补足

也就是以右表为基础,匹配的到的(相同的)显示数据,匹配不到的一律都是空值
 

总结 高阶语句

涉及到面试(面试问题实例,重点记)

1、select、order by和limit的一个集合
① mysql 数据库 如何查一张表;     (select语法)
② 查ky29表中的id 和name           (指定字段的查询)
③ 查KY29表中score大于90的怎么查    (select配合  where条件过滤的查询)
④ 查询KY9表中前4行记录怎么查看      (select 配合limit怎么查询)
⑤ KY29表  表中第四行记录的后的2行记录怎么看  (select集合         limit输出指定以下的多行内容)
⑥ KY29表 怎么查看最后的三行记录    (select 结合order by {asc|desc}排序之后的limit查询)

2、内连接、左连接、右连接是干嘛的
内连接: inner join
左连接: left join
右连接:right join

3、子查询 (多表查询)
2表关联查询条件,写一个子查询sql
select id,name from KY29 where name in (select name from infos);

增删改查等基础也要会

优化和视图也要会,MySQL的架构也常问(重点),见后面几章的内容

二、存储过程⭐⭐⭐

1、概述

前面学习的 MySQL 相关知识都是针对一个表或几个表的单条 SQL 语句,使用这样的SQL 语句虽然可以完成用户的需求,但在实际的数据库应用中,有些数据库操作可能会非常复杂,可能会需要多条 SQL 语句一起去处理才能够完成,这时候就可以使用存储过程, 轻松而高效的去完成这个需求,有点类似shell脚本里的函数

2、简介

1、存储过程是一组为了完成特定功能的SQL语句集合。  两个点 第一 触发器(定时任务) 第二个判断 
2、存储过程这个功能是从5.0版本才开始支持的,它可以加快数据库的处理速度,增强数据库在实际应用中的灵活性。存储过程在使用过程中是将常用或者复杂的工作预先使用SQL语句写好并用一个指定的名称存储起来,这个过程经编译和优化后存储在数据库服务器中。当需要使用该存储过程时,只需要调用它即可。操作数据库的传统 SQL 语句在执行时需要先编译,然后再去执行,跟存储过程一对比,明显存储过程在执行上速度更快,效率更高

开发人员       访问select 如果访问过多100万 触发存储过程
 


存储过程在数据库中创建并保存,它不仅仅是 SQ语句的集合,还可以加入一些特殊的控制结构,也可以控制数据的访问方式。存储过程的应用范围很广,例如封装特定的功能、 在不同的应用程序或平台上执行相同的函数等等。


3、存储过程的优点

(1)执行一次后,会将生成的二进制代码驻留缓冲区,提高执行效率
(2)SQL语句加上控制语句的集合,灵活性高
(3)在服务器端存储,客户端调用时,降低网络负载
(4)可多次重复被调用,可随时修改,不影响客户端调用
(5)可完成所有的数据库操作,也可控制数据库的信息访问权限


语法:

CREATE PROCEDURE <过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
<过程名>:尽量避免与内置的函数或字段重名
<过程体>:语句
[ IN | OUT | INOUT ] <参数名><类型>


示例(不带参数的创建)

##创建存储过程##

DELIMITER $$                            #将语句的结束符号从分号;临时改为两个$$(可以自定义)
CREATE PROCEDURE Proc()                    #创建存储过程,过程名为Proc,不带参数
-> BEGIN                                #过程体以关键字 BEGIN 开始
-> create table mk (id int (10), name char(10),score int (10));
-> insert into mk values (1, 'wang',13);
-> select * from mk;                    #过程体语句
-> END $$                                #过程体以关键字 END 结束
DELIMITER ;                                #将语句的结束符号恢复为分号

##调用存储过程##

CALL Proc();

I    存储过程的主体都分,被称为过程体
II   以BEGIN开始,以END结束,若只有一条sQL语句,则可以省略BEGIN-END
III  以DELIMITER开始和结束  
mysgl>DEL工M工TER $$      $$是用户自定义的结束符 
省略存储过程其他步骤
mysql>DELIMITER ;  分号前有空格


##查看存储过程##

格式:
SHOW CREATE PROCEDURE [数据库.]存储过程名;        #查看某个存储过程的具体信息

mysql> show create procedure proc\G
*************************** 1. row ***************************
           Procedure: proc
            sql_mode: PIPES_AS_CONCAT,ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_D_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER="root"@"localhost" PROCEDURE "proc"()
begin
select id,name from info;
update info set score='10' where name='tiqnai';
end
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
1 row in set (0.00 sec)

#查看存储过程
SHOW PROCEDURE STATUS 

#查看指定存储过程信息
mysql> SHOW PROCEDURE STATUS like '%proc%'\G

*************************** 1. row ***************************
                  Db: info
                Name: proc
                Type: PROCEDURE
             Definer: root@localhost
            Modified: 2021-07-15 05:45:21
             Created: 2021-07-15 05:45:21
       Security_type: DEFINER
             Comment: 
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
1 row in set (0.01 sec)


##存储过程的参数##

IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)

即表示调用者向过程传入值,又表示过程向调用者传出值(只能是变量)


举例:

mysql> delimiter @@
mysql> create procedure proc (in inname varchar(40))     #行参
    -> begin
    -> select * from info where name=inname;
    -> end @@
mysql> delimiter @@            
mysql> call proc2('wangwu');              #实参
+--------+-------+---------+
| name   | score | address |
+--------+-------+---------+
| wangwu | 80.00 | beijing |
+--------+-------+---------+
1 row in set (0.00 sec)


##修改存储过程##

ALTER PROCEDURE <过程名>[<特征>... ]
ALTER PROCEDURE GetRole MODIFIES SQL DATA SQL SECURITY INVOKER;
MODIFIES sQLDATA:表明子程序包含写数据的语句
SECURITY:安全等级
invoker:当定义为INVOKER时,只要执行者有执行权限,就可以成功执行。


##删除存储过程##

存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。

DROP PROCEDURE IF EXISTS Proc;

存储过程了解怎么写(方式)及其作用即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值