目录
一、子查询——Subquery
子查询也被称作为内查询或者嵌套查询,是指一个查询语句里面还嵌套着另一个查询语句,即SQL语句调用另一个Select子句。子查询语句是先于主查询语句被执行的,其结果作为外层的条件返回给主查询进行下一步查询过滤。
子语句可以与主语句所查询的表相同,也可以是不同表;
子语句中的SQL语句是为了最后过滤出一个结果集,用于主语句的判断条件;
in是作为主表和另一个表的连接的语法
1.环境准备
mysql> show tables;
+-----------------+
| Tables_in_class |
+-----------------+
| class |
| test |
| test2 |
+-----------------+
3 rows in set (0.00 sec)
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> create table class2(id int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into class2 values(1),(2),(3);
Query OK, 3 rows affected (0.10 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from class2;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
2.In——查询已知的值的数据记录
IN 用来判断某个值是否在给定的结果集中,通常结合子查询来使用
<表达式> [NOT] IN <子查询>
mysql> select id,name,score from class where id in(select id from class2);
#先查询class2数据表中的id字段列 将查询到的结果id字段列作为一个已知的值的数据记录;再根据已知的值的数据记录查询class数据表中id,name,score字段列
+----+------+-------+
| id | name | score |
+----+------+-------+
| 1 | cxk | 80.00 |
| 2 | wyb | 80.00 |
| 3 | zyx | 95.00 |
+----+------+-------+
3 rows in set (0.09 sec)
mysql> select * from test2;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 3 | zyx | 95.00 | wuhan | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+---------+--------+
3 rows in set (0.00 sec)
mysql> select id,name,score from class where id in(select id from test2 where score >= 90);
#先查询test2数据表判断条件为 score分数大于等于90分的数据作为id列 以此作为查询条件从class数据表中获取数据
+----+------+-------+
| id | name | score |
+----+------+-------+
| 3 | zyx | 95.00 |
| 5 | zs | 90.00 |
| 6 | zjl | 90.00 |
+----+------+-------+
3 rows in set (0.00 sec)
mysql> select id,name,score from class where name in(select name from test2 whhere score >= 90);
+----+------+-------+
| id | name | score |
+----+------+-------+
| 3 | zyx | 95.00 |
| 5 | zs | 90.00 |
| 6 | zjl | 90.00 |
+----+------+-------+
3 rows in set (0.00 sec)
mysql> select id,name,score from class where id in(select name from test2 wherre score >= 90);
Empty set (0.00 sec)
子查询的判断条件主查询语句必须与子查询语句中的字段一致
当表达式与子查询返回的结果集中的某个值相等时,返回 TRUE,否则返回 FALSE。 若启用了 NOT 关键字,则返回值相反。需要注意的是,子查询只能返回一列数据,如果需 求比较复杂,一列解决不了问题,可以使用多层嵌套的方式来应对。 多数情况下,子查询都是与 SELECT 语句一起使用的
2.1子查询——Insert
子查询还可以用在 INSERT 语句中。子查询的结果集可以通过 INSERT 语句插入到其 他的表中
mysql> show tables;
+-----------------+
| Tables_in_class |
+-----------------+
| c |
| class |
| class2 |
| test |
| test2 |
+-----------------+
5 rows in set (0.00 sec)
mysql> select * from test2;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 3 | zyx | 95.00 | wuhan | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+---------+--------+
3 rows in set (0.01 sec)
mysql> delete from test2;
Query OK, 3 rows affected (0.00 sec)
mysql> select * from test2;
Empty set (0.00 sec)
mysql> insert into test2 select * from class where id in(select id from class));
#先遍历class数据表中id的字段列 然后根据查询到的字段列插入到test2数据表中
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from test2;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
2.2子查询——Update
UPDATE 语句也可以使用子查询。UPDATE 内的子查询,在 set 更新内容时,可以是单独的一列,也可以是多列。
mysql> select * from test2;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> update test2 set score=85 where id in(select id from class where id=1);;
Query OK, 1 row affected (0.00 sec)
#更新test2数据表中 根据查询关联表class数据表id=1的数据内容 修改id=1的字段的分数为85分
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test2;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
2.3子查询——Delete
mysql> select * from test2 where score > 90;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 3 | zyx | 95.00 | wuhan | 2 |
+----+------+-------+---------+--------+
1 row in set (0.00 sec)
mysql> delete from test2 where id in (select id from class where score > 90);
#先查询class数据表中 得分大于90分的 删除test2数据表中大于90分的数据
Query OK, 1 row affected (0.00 sec)
mysql> select * from test2;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
5 rows in set (0.00 sec)
3.Not In——表示否定,不在子查询的结果集里
在 IN 前面还可以添加 NOT,其作用与IN相反,表示否定(即不在子查询的结果集里面)
mysql> select * from test2;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
5 rows in set (0.00 sec)
mysql> delete from test2 where id not in(select id where score <85);
#删除test2数据表条件判断 取反 遍历score分数 小于85分的 也就是删除test2数据表中分数大于85分的所有数据
Query OK, 4 rows affected (0.00 sec)
mysql> select * from test2;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 2 | wyb | 80.00 | beijing | 1 |
+----+------+-------+---------+--------+
1 row in set (0.00 sec)
3.Exists——判断查询结果集是否为空
mysql> select sum(score) from test2 where exists(select id from test2 where score > 80);
#先查询test2数据表中id字段列 判断score分数是否大于80分 exists判断子查询结果是否为空,如果为空返回false 子查询结果为空 那么 不执行test2数据表的求和
+------------+
| sum(score) |
+------------+
| NULL |
+------------+
1 row in set (0.00 sec)
mysql> select * from test2;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 2 | wyb | 80.00 | beijing | 1 |
+----+------+-------+---------+--------+
1 row in set (0.00 sec)
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> select sum(score) from class where exists(select id from test2 where sccore > 80);
#先查询test2数据表中id字段列 判断条件score分数是否大于80 exists判断子查询结果为空 依旧不执行class数据表的sum求和
+------------+
| sum(score) |
+------------+
| NULL |
+------------+
1 row in set (0.00 sec)
mysql> select sum(score) from class where exists(select id from test2 where score <= 80);
#先查询test2数据表 判断条件为小于等于80 exists子查询结果为TRUE 为真 那么执行前面的class查询语句 查询所有字段并且Sum求和
+------------+
| sum(score) |
+------------+
| 523.00 |
+------------+
1 row in set (0.00 sec)
4.子查询——别名
mysql> select id,name from (select id,name from class);
ERROR 1248 (42000): Every derived table must have its own alias
#报错的原因是子查询语句中select查询的表名是一个完整的结果集,主查询语句不能识别子查询的结果(不能识别子查询语句输出的整个数据表的数据内容)
mysql> select id,name from (select id,name from class) a;
#如果将子查询语句的输出数据当做一个别名 交由主查询语句来识别 那么可以显示查询的数据结果内容
+----+------+
| id | name |
+----+------+
| 1 | cxk |
| 2 | wyb |
| 3 | zyx |
| 4 | xzq |
| 5 | zs |
| 6 | zjl |
+----+------+
6 rows in set (0.00 sec)
二、视图——View
视图(View):优化操作+安全方案,视图可以理解为数据库中的一张虚拟的数据表,这张虚拟表中不包含真实数据,只是做了真实数据的映射(相当于做了一个真实数据的快捷方式 或者 动态结果的结果集)
1.视图与表的联系与区别
1.1联系
视图是基础表之上建立的表,它的结构(即所定义的列)和内容(即所有数据行)都来自基本表,它依据基本表存在而存在。一个视图可以对应一个基本表,也可以对应多个基本表。视图是基本表的抽象和在逻辑意义上建立的新关系。
1.2区别
- 视图是已经编译好的SQL语句
- 视图没有实际操作的物理记录,是基于数据表上的一张表(一定要有数据表才能有视图)
- 表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表可以及时修改数据,但视图只能有创建的语句来修改
- 视图是已查看数据表的一种方式,可以查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图可以不给用户接触数据表,从而不知道表结构。
- 表属于全局模式的表,是实表;视图属于局部模式的表,是虚表
- 视图的建立和删除只影响视图本身,不影响对应的基本表(更新视图数据,数据表的数据也会一起更改)
2.实际操作
2.1创建视图
mysql> create view v_score as select * from class;
#创建视图 视图表v_score 基于class数据表而存在
Query OK, 0 rows affected (0.00 sec)
mysql> desc class;
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id | int(6) | NO | PRI | NULL | |
| name | char(8) | YES | | NULL | |
| score | decimal(5,2) | YES | | NULL | |
| address | varchar(40) | YES | | NULL | |
| cardid | int(6) | YES | | NULL | |
+---------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql> desc v_score;
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id | int(6) | NO | | NULL | |
| name | char(8) | YES | | NULL | |
| score | decimal(5,2) | YES | | NULL | |
| address | varchar(40) | YES | | NULL | |
| cardid | int(6) | YES | | NULL | |
+---------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
视图与数据表的区别是主键
mysql> show table status\G;
*************************** 1. row ***************************
Name: c
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 6
Avg_row_length: 2730
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-27 15:24:36
Update_time: 2024-03-27 15:24:36
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 2. row ***************************
Name: class
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 6
Avg_row_length: 2730
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-26 14:27:34
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 3. row ***************************
Name: class2
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 3
Avg_row_length: 5461
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-27 13:25:50
Update_time: 2024-03-27 13:26:44
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 4. row ***************************
Name: test
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 6
Avg_row_length: 2730
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-26 18:44:08
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 5. row ***************************
Name: test2
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 1
Avg_row_length: 16384
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2024-03-26 18:46:48
Update_time: 2024-03-27 16:15:17
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
*************************** 6. row ***************************
Name: v_score
Engine: NULL
Version: NULL
Row_format: NULL
Rows: NULL
Avg_row_length: NULL
Data_length: NULL
Max_data_length: NULL
Index_length: NULL
Data_free: NULL
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: NULL
Checksum: NULL
Create_options: NULL
Comment: VIEW
6 rows in set (0.00 sec)
ERROR:
No query specified
创建的视图看不到任何的状态信息
2.2修改原表数据
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> select * from v_score;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> update class set score=85 where name='cxk';
Query OK, 1 row affected (0.10 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> select * from v_score;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
修改原表的数据,视图的数据会变动
2.3修改视图数据
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> select * from v_score;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 85.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> update v_score set score=92 where name='cxk';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from v_score;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 92.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
mysql> select * from class;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 92.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.00 sec)
修改视图的数据,那么原表的数据也会变更
3.总结
- 修改表不能修改以函数、符合函数方式计算出来的字段
- 视图的存在是为了查询更加方便,为了增强安全性
三、Null值——缺失
在SQL语句使用过程中,通常使用NULL表示缺失的值,也就是在表中该字段是没有值的。如果在创建表时,指定某字段不能为空(Not Null),不指定则默认可以为空。在向表中插入记录或者更新记录的时候,如果该字段没有Not Null值,且没有任何值,这时新记录的字段数据为Null。
注意:Null值域数字0或者空白的字段是不用的,值为Null是字段没有值;
在使用SQL语句中,使用Is Null可以判断表内的某个字段是不是Null值,相反的用Is Not Null可以判断不是Null值
mysql> select length(null),length(''),length('cxk');
+--------------+------------+---------------+
| length(null) | length('') | length('cxk') |
+--------------+------------+---------------+
| NULL | 0 | 3 |
+--------------+------------+---------------+
1 row in set (0.00 sec)
#null占用字节为null占用空间 空占用字节为0字节不占用空间 cxk字段占用字节为3个字节
#这样对比一目了然 可以更清楚的看到三个值之间的对比 更方便的了解到null值和空值占用的字节数
#当使用count计数时,null值会自动忽略 但是空值的话会加入计算
mysql> alter table class add length varchar(50);
Query OK, 0 rows affected (0.14 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select * from class;
+----+------+-------+----------+--------+--------+
| id | name | score | address | cardid | length |
+----+------+-------+----------+--------+--------+
| 1 | cxk | 92.00 | nanjing | 1 | NULL |
| 2 | wyb | 80.00 | beijing | 1 | NULL |
| 3 | zyx | 95.00 | wuhan | 2 | NULL |
| 4 | xzq | 88.00 | shanghai | 2 | NULL |
| 5 | zs | 90.00 | yunnan | 3 | NULL |
| 6 | zjl | 90.00 | beijing | 4 | NULL |
+----+------+-------+----------+--------+--------+
6 rows in set (0.00 sec)
mysql> update class set length='' where id=1;
Query OK, 1 row affected (0.09 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from class where length is null;
+----+------+-------+----------+--------+--------+
| id | name | score | address | cardid | length |
+----+------+-------+----------+--------+--------+
| 3 | zyx | 95.00 | wuhan | 2 | NULL |
| 4 | xzq | 88.00 | shanghai | 2 | NULL |
| 5 | zs | 90.00 | yunnan | 3 | NULL |
| 6 | zjl | 90.00 | beijing | 4 | NULL |
+----+------+-------+----------+--------+--------+
4 rows in set (0.00 sec)
mysql> select * from class where length is not null;
+----+------+-------+---------+--------+--------+
| id | name | score | address | cardid | length |
+----+------+-------+---------+--------+--------+
| 1 | cxk | 92.00 | nanjing | 1 | |
| 2 | wyb | 80.00 | beijing | 1 | |
+----+------+-------+---------+--------+--------+
2 rows in set (0.00 sec)
mysql> select count(length) from class;
+---------------+
| count(length) |
+---------------+
| 2 |
+---------------+
1 row in set (0.00 sec)
#count计数统计数量的时候 null值不会计数总数
四、连接查询
Mysql的连接查询,通常都是将来自两个或多个表的记录行结合起来,基于这些表之间的共同字段,进行数据的拼接。首先,要确定一个主表作为结果集,然后将其他表的行有选择性的连接到该主表。
mysql> select * from class;
+----+------+-------+----------+--------+--------+
| id | name | score | address | cardid | length |
+----+------+-------+----------+--------+--------+
| 1 | cxk | 92.00 | nanjing | 1 | |
| 2 | wyb | 80.00 | beijing | 1 | |
| 3 | zyx | 95.00 | wuhan | 2 | NULL |
| 4 | xzq | 88.00 | shanghai | 2 | NULL |
| 5 | zs | 90.00 | yunnan | 3 | NULL |
| 6 | zjl | 90.00 | beijing | 4 | NULL |
+----+------+-------+----------+--------+--------+
6 rows in set (0.00 sec)
mysql> select * from test;
+----+------+-------+----------+--------+
| id | name | score | address | cardid |
+----+------+-------+----------+--------+
| 1 | cxk | 80.00 | nanjing | 1 |
| 2 | wyb | 80.00 | beijing | 1 |
| 3 | zyx | 95.00 | wuhan | 2 |
| 4 | xzq | 88.00 | shanghai | 2 |
| 5 | zs | 90.00 | yunnan | 3 |
| 6 | zjl | 90.00 | beijing | 4 |
+----+------+-------+----------+--------+
6 rows in set (0.01 sec)
mysql> select * from test2;
+----+------+-------+---------+--------+
| id | name | score | address | cardid |
+----+------+-------+---------+--------+
| 2 | wyb | 80.00 | beijing | 1 |
+----+------+-------+---------+--------+
1 row in set (0.00 sec)
1.内连接——Inner Join
内连接就是两张或多张表中同时符合某种条件的数据记录的集合(可以理解为交集)。通常在from子句中使用关键字inner join来连接多张表,并使用On子句设置连接条件,内连接是系统默认的表连接,所以在from子句后可以省略Inner关键字,只使用Join。同时有多个表时,也可以连续使用Inner Join来实现多表的内连接,建议最好不要超过三个表
SELECT 字段列1,字段列2...FROM table1_name INNER JOIN table2_name ON table1.列名 = table2.列名;
mysql> select a.id,a.name from class a inner join test2 b on a.id=b.id;
+----+------+
| id | name |
+----+------+
| 2 | wyb |
+----+------+
1 row in set (0.00 sec)
2.左连接——Left Join
左连接也可以被称为左外连接,在from子句中使用Left Join或者Left Outer Join关键字来表示。左连接以左侧的数据表作为基础表,接收左侧数据表中所有的行,并用这些行与右侧数据表进行匹配,也就是匹配到左侧数据表中的所有内容以及左数据表和右侧数据表符合条件的行。
mysql> select * from class a left join test2 b on a.id=b.id;
+----+------+-------+----------+--------+--------+------+------+-------+---------+--------+
| id | name | score | address | cardid | length | id | name | score | address | cardid |
+----+------+-------+----------+--------+--------+------+------+-------+---------+--------+
| 2 | wyb | 80.00 | beijing | 1 | | 2 | wyb | 80.00 | beijing | 1 |
| 1 | cxk | 92.00 | nanjing | 1 | | NULL | NULL | NULL | NULL | NULL |
| 3 | zyx | 95.00 | wuhan | 2 | NULL | NULL | NULL | NULL | NULL | NULL |
| 4 | xzq | 88.00 | shanghai | 2 | NULL | NULL | NULL | NULL | NULL | NULL |
| 5 | zs | 90.00 | yunnan | 3 | NULL | NULL | NULL | NULL | NULL | NULL |
| 6 | zjl | 90.00 | beijing | 4 | NULL | NULL | NULL | NULL | NULL | NULL |
+----+------+-------+----------+--------+--------+------+------+-------+---------+--------+
6 rows in set (0.00 sec)
左连接中左表的记录将会全部表示出来,而右表只会显示符合搜索条件的记录,右表记录不足的地方均为 NULL。
3.右连接——Right Join
右连接也被称为右外连接,在 FROM 子句中使用 RIGHT JOIN 或者 RIGHT OUTER JOIN 关键字来表示。右连接跟左连接正好相反,它是以右表为基础表,用于接收右表中的所有行,并用这些记录与左表中的行进行匹配,也就是匹配到右侧数据表中的所有内容以及右数据表和左侧数据表符合条件的行。
mysql> select * from class a right join test2 b on a.id=b.id;
+------+------+-------+---------+--------+--------+----+------+-------+---------+--------+
| id | name | score | address | cardid | length | id | name | score | address | cardid |
+------+------+-------+---------+--------+--------+----+------+-------+---------+--------+
| 2 | wyb | 80.00 | beijing | 1 | | 2 | wyb | 80.00 | beijing | 1 |
+------+------+-------+---------+--------+--------+----+------+-------+---------+--------+
1 row in set (0.00 sec)
在右连接的查询结果集中,除了符合匹配规则的行外,还包括右表中有但是左表中不匹 配的行,这些记录在左表中以 NULL 补足
五、存储过程
1.概述
存储过程是一组为了完成特定功能的SQL语句集合。 两个点 第一 触发器(定时任务) 第二个判断
存储过程这个功能是从5.0版本才开始支持的,它可以加快数据库的处理速度,增强数据库在实际应用中的灵活性。存储过程在使用过程中是将常用或者复杂的工作预先使用SQL语句写好并用一个指定的名称存储起来,这个过程经编译和优化后存储在数据库服务器中。当需要使用该存储过程时,只需要调用它即可。操作数据库的传统 SQL 语句在执行时需要先编译,然后再去执行,跟存储过程一对比,明显存储过程在执行上速度更快,效率更高
存储过程在数据库中L 创建并保存,它不仅仅是 SQ语句的集合,还可以加入一些特殊的控制结构,也可以控制数据的访问方式。存储过程的应用范围很广,例如封装特定的功能、 在不同的应用程序或平台上执行相同的函数等等。
2.存储过程的优点
- 执行一次后,会将生成的二进制代码驻留缓冲区,提高执行效率
- SQL语句加上控制语句的集合,灵活性高
- 在服务器端存储,客户端调用时,降低网络负载
- 可多次重复被调用,可随时修改,不影响客户端调用
- 可完成所有的数据库操作,也可控制数据库的信息访问权限
3.语法 创建存储过程
CREATE PROCEDURE <过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
<过程名>:尽量避免与内置的函数或字段重名
<过程体>:语句
[ IN | OUT | INOUT ] <参数名><类型>
mysql> delimiter $$
#将语句的结束符号从分号;临时改为两个$$(可以自定义)
mysql> create procedure class()
#创建存储过程,过程名为class,不带参数
-> begin
#过程体以关键字 BEGIN 开始
-> create table class3(id int,name varchar(8),score decimal(5,2));
-> insert into class3 values(1,'wsc',98),(2,'ljc',95);
-> select * from class3;
#过程体语句
-> END $$
#过程体以关键字 END 结束
Query OK, 0 rows affected (0.12 sec)
mysql> DELIMITER ;
#将语句的结束符号恢复为分号
4.调用查看存储过程
4.1调用存储过程
mysql> call cxk();
+------+------+-------+
| id | name | score |
+------+------+-------+
| 1 | wsc | 98.00 |
| 2 | ljc | 95.00 |
+------+------+-------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
4.2查看存储过程
mysql> show create procedure class\G
*************************** 1. row ***************************
Procedure: class
sql_mode: PIPES_AS_CONCAT,ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER="root"@"localhost" PROCEDURE "class"()
begin
create table class3(id int,name varchar(8),score decimal(5,2));
insert into class3 values(1,'wsc',98),(2,'ljc',95);
select * from class3;
END
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec)
4.3查看指定存储过程
mysql> show procedure status like '%class%'\G;
*************************** 1. row ***************************
Db: class
Name: class
Type: PROCEDURE
Definer: root@localhost
Modified: 2024-03-27 18:46:06
Created: 2024-03-27 18:46:06
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)
ERROR:
No query specified
5.参数
- IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
- OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
- INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
表示调用者向过程传入值,又表示过程向调用者传出值(只能是变量)
mysql> show tables;
+-----------------+
| Tables_in_class |
+-----------------+
| c |
| class |
| class2 |
| class3 |
| test |
| test2 |
| v_score |
+-----------------+
7 rows in set (0.00 sec)
mysql> delimiter @@
mysql> create procedure test3 (in inname varchar(8))
#形参
-> begin
-> select * from class where name=inname;
-> end @@
Query OK, 0 rows affected (0.08 sec)
mysql> delimiter ;
mysql> call test3('cxk');
+----+------+-------+---------+--------+--------+
| id | name | score | address | cardid | length |
+----+------+-------+---------+--------+--------+
| 1 | cxk | 92.00 | nanjing | 1 | |
+----+------+-------+---------+--------+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
- 定义方式与作用域不同。形参是在函数定义中声明的,用于在函数体内进行使用,但它们只在函数执行期间存在,函数调用结束后,形参的作用域结束。实参则是在主调函数中定义的,用于传递值给形参,在函数调用期间,实参的值被传递给形参。
- 内存占用不同。形参本质上是一个名字,它不占用内存空间,直到函数被调用时,形参才被分配内存空间。实参则是一个已经占用内存空间的变量,它在程序运行期间一直存在。
- 传递机制不同。在传值调用中,只有实参的值被使用;而在引用调用中,实参的地址被传递给形参,这意味着对形参的任何修改都会影响到实参本身。
简而言之,形参是函数定义中的占位符,用于接收实参传递的值,而实参是在函数调用时传递给形参的实际值。
6.修改删除存储过程
6.1修改存储过程
ALTER PROCEDURE <过程名>[<特征>... ]
SECURITY:安全等级
invoker:当定义为INVOKER时,只要执行者有执行权限,就可以成功执行。
6.2删除存储过程
存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。
mysql> drop procedure if exists cxk;
Query OK, 0 rows affected (0.00 sec)
mysql> call cxk();
ERROR 1305 (42000): PROCEDURE class.cxk does not exist
mysql> show create procedure cxk\G;
ERROR 1305 (42000): PROCEDURE cxk does not exist
ERROR:
No query specified
六、总结
1.子查询
- In:查询已知的值数据记录
- Not In:表示否定,不存在子查询结果集里(相当于取反)
- Exists:判断查询结果集是否为空(空返回False,非空返回TRUE)
2.视图——View
无论修改视图还是原表数据,都会随之一起更改
3.缺失值——Null
- Null:占用空间Null值
- 空值:占用空间为0
4.连接查询——内 左 右
- 内连接:Inner Join
- 左连接:Left Join
- 右连接:Right Join
5.存储过程——Procedure
5.1创建存储过程
delimiter $$
#将语句的结束符号从分号;临时改为两个$$(可以自定义)
mysql> create procedure class()
#创建存储过程,过程名为class,不带参数
-> begin
#过程体以关键字 BEGIN 开始
-> create table class3(id int,name varchar(8),score decimal(5,2));
-> insert into class3 values(1,'wsc',98),(2,'ljc',95);
-> select * from class3;
#过程体语句
-> END $$
#过程体以关键字 END 结束
Query OK, 0 rows affected (0.12 sec)
mysql> DELIMITER ;
#将语句的结束符号恢复为分号
5.2查看存储过程
show create procedure Procedure_name
5.3调用存储过程
call Procedure_name();
6.参数
- IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
- OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
- INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)