模板 test、class、class0
mysql> select * from test;
+--------+--------+------+----------+
| idcard | name | age | hobbid |
+--------+--------+------+----------+
| 01 | lizi | 18 | guangjie |
| 02 | monor | 22 | zhaijia |
| 03 | sansan | 9 | wan |
+--------+--------+------+----------+
3 rows in set (0.00 sec)mysql> select * from class;
+------+--------+-------+----------+--------+
| id | name | score | address | course |
+------+--------+-------+----------+--------+
| 0001 | yiyi | 78.00 | shanghai | 1 |
| 0002 | lizi | 92.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0004 | sisi | 60.00 | nanjing | 3 |
| 0005 | wuwu | 37.00 | shanghai | 3 |
| 0006 | liuliu | 66.00 | henan | 2 |
| 0007 | qiqi | 13.00 | hangzhou | 4 |
+------+--------+-------+----------+--------+
7 rows in set (0.00 sec)mysql> select * from class0;
+------+--------+-------+----------+--------+
| id | name | score | address | course |
+------+--------+-------+----------+--------+
| 0001 | yiyi | 78.00 | shanghai | 1 |
| 0002 | lizi | 92.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0004 | sisi | 60.00 | nanjing | 3 |
| 0005 | wuwu | 37.00 | shanghai | 3 |
| 0006 | liuliu | 66.00 | henan | 2 |
| 0007 | qiqi | 13.00 | hangzhou | 4 |
+------+--------+-------+----------+--------+
7 rows in set (0.00 sec)
六、子查询
子查询也被称作内查询或者嵌套查询,是指在一个查询语句中还嵌套着另一个查询语句;
子查询语句先于主查询语句被执行,其结果作为外层的条件返回给主查询进行下一步过滤;
子语句可以与主语句所查询的表相同,也可以是不同表
select 字段1,字段2 from 表名1 where 字段1 in (select 字段1 from 表名1/2 where 字段2/3 取值范围);例:
select id,score from class where id in (select id from class where score > 60);
上面的查询语句中:
主语句为:select id,score from class where id
子语句为:select id from class where score > 60
子句中的sql语句过滤出一个结果集,用于主语句的判断条件
子查询通过 in 将主表与子表关联/连接
多表查询
in 用来判断某个值是否在给定的结果集中,通常结合子查询来使用
当表达式与子查询返回的结果集中的某个值相等时,返回 true,否则返回 false。
若启用了 not 关键字,则返回值相反。
主查询 in 子查询
主查询 not in 子查询
需要注意的是,子查询只能返回一列数据,如果需 求比较复杂,一列解决不了问题,可以使用多层嵌套的方式来应对。子查询一般与 select 语句一起使用的
以clss为主表,test为子表,查询两表中名字相同的记录
mysql> select id,name,score from class where name in (select name from teest);
+------+-------+-------+
| id | name | score |
+------+-------+-------+
| 0002 | lizi | 92.00 |
| 0003 | monor | 88.00 |
+------+-------+-------+
2 rows in set (0.00 sec)
子查询不仅可以在 select 语句中使用,在 inter、update、delete 中也同样适用;
子查询用于 insert 语句
#通过not in 将class0表中比class表多的数据添加进了class表
mysql> insert into class select * from class0 where name not in(select name from class);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> select * from class;
+------+--------+-------+----------+--------+
| id | name | score | address | course |
+------+--------+-------+----------+--------+
| 0001 | yiyi | 78.00 | shanghai | 1 |
| 0002 | lizi | 92.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0004 | sisi | 60.00 | nanjing | 3 |
| 0005 | wuwu | 37.00 | shanghai | 3 |
| 0006 | liuliu | 66.00 | henan | 2 |
| 0007 | qiqi | 13.00 | hangzhou | 4 |
+------+--------+-------+----------+--------+
7 rows in set (0.00 sec)
子查询用于 update 语句
update class set score='100' where name in (select name from test where name='lizi');;
子查询用于 delete 语句
delete from 表名 where 唯一字段1 in(select 唯一字段1 where 字段2 范围值);
#用同一个表当作主句和子句,删除成绩小于60的数据
mysql> delete from class where id in(select id where score<60);
Query OK, 2 rows affected (0.00 sec)mysql> select * from class;
+------+--------+-------+----------+--------+
| id | name | score | address | course |
+------+--------+-------+----------+--------+
| 0001 | yiyi | 78.00 | shanghai | 1 |
| 0002 | lizi | 92.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0004 | sisi | 60.00 | nanjing | 3 |
| 0006 | liuliu | 66.00 | henan | 2 |
+------+--------+-------+----------+--------+
5 rows in set (0.00 sec)
exists 查询
exists 这个关键字在子查询时,主要用于判断子查询的结果集是否为空。
如果不为空, 则返回 true,执行主句;反之,则返回 false,不执行主句
mysql> select count(id) from class where exists(select idcard from test where name='yiyi');
+-----------+
| count(id) |
+-----------+
| 0 |
+-----------+
1 row in set (0.00 sec)
#当子句判断结果为空(false)时,不会执行主句的命令mysql> select count(id) from class where exists(select idcard from test where name='monor');
+-----------+
| count(id) |
+-----------+
| 7 |
+-----------+
1 row in set (0.00 sec)
#当字句判断非空(true)时,则执行主句的命令
多层嵌套查询
在嵌套的时候,子查询内部还可以再次嵌套新的子查询,也就是说可以多层嵌套。
mysql> select * from class where name in(select name from test where name in(select name frmom class where score>60));
+------+-------+--------+---------+--------+
| id | name | score | address | course |
+------+-------+--------+---------+--------+
| 0002 | lizi | 100.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
+------+-------+--------+---------+--------+
2 rows in set (0.00 sec)mysql> select * from class where name in(select name from test where name in(select name from class where score>88));
+------+------+--------+---------+--------+
| id | name | score | address | course |
+------+------+--------+---------+--------+
| 0002 | lizi | 100.00 | henan | 1 |
+------+------+--------+---------+--------+
1 row in set (0.00 sec)
子查询,别名as
将结果集做为一张表进行查询的时候,我们需要为它设置别名;
"表名"的位置其实是一个完整结果集,mysql并不能直接识别(字段),所以需要为它设置别名,来构成一个"表名"
mysql> select * from (select * from class limit 3) as a order by score desc;
+------+-------+--------+----------+--------+
| id | name | score | address | course |
+------+-------+--------+----------+--------+
| 0002 | lizi | 100.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0001 | yiyi | 78.00 | shanghai | 1 |
+------+-------+--------+----------+--------+
3 rows in set (0.00 sec)
#子句将class表的前三行拎出来并设置别名为a,主句在以a表的score字段查询并排序
MySQL视图
视图是数据库中的虚拟表,这张虚拟表中不包含真实数据,只是做了真实数据的映射
动态保存结果集(数据);可以优化操作、以视图对外展示安全
视图是动态的,基本表(视图)数据修改后,视图(基本表)也会变化
功能
简化查询结果集,灵活查询,可以针对不同用户呈现不同结果集,相对有更高的安全性;
本质而言视图是一种select结果集的呈现
PS:视图适合于多表连接浏览时使用;不适合增、删、改
而存储过程适合于使用较频繁的SQL语句,可以提高执行效率
视图和表的区别和联系
区别:
1.视图是已经编译好的sql语句,表不是
2.试图没有实际的物理记录,表有
show table status\G;
#可以看到,视图下的数据结构都是null可以防止信息泄露
mysql> show table status\G;
*************************** 1. row ***************************Name: classEngine: InnoDBVersion: 10Row_format: DynamicRows: 7Avg_row_length: 2340Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: NULLCreate_time: 2024-03-25 21:13:29Update_time: 2024-03-27 01:27:04Check_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
*************************** 2. row ***************************Name: class0Engine: InnoDBVersion: 10Row_format: DynamicRows: 7Avg_row_length: 2340Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: NULLCreate_time: 2024-03-27 00:55:36Update_time: 2024-03-27 00:55:36Check_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
*************************** 3. row ***************************Name: testEngine: InnoDBVersion: 10Row_format: DynamicRows: 2Avg_row_length: 8192Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: NULLCreate_time: 2024-03-27 00:18:46Update_time: 2024-03-26 20:14:38Check_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
*************************** 4. row ***************************Name: v_nameEngine: NULLVersion: NULLRow_format: NULLRows: NULLAvg_row_length: NULLData_length: NULL
Max_data_length: NULLIndex_length: NULLData_free: NULLAuto_increment: NULLCreate_time: NULLUpdate_time: NULLCheck_time: NULLCollation: NULLChecksum: NULLCreate_options: NULLComment: VIEW
4 rows in set (0.00 sec)ERROR:
No query specified
3.表占用物理空间,而视图不占用物理空间;
视图只是逻辑概念的存在,表可以对它修改;
但视图只能用创建语句来修改
4.视图可以查询数据表中由某些字段构成的数据;
视图可以不给用户接触数据表,从而不暴露表结构
5.表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表
6.视图的建立和删除只影响视图本身,不影响对应的基本表;
但修改视图的数据,会影响到基本表
联系:
视图(view)是在基本表之上建立的表;它的结构(列)和内容(数据行)都来自基本表;
视图依赖基本表存在而存在;一个视图对应一个或多个基本表;
视图是基本表的抽象和在逻辑意义上建立的新关系
多表创建视图
mysql> create view v_stu as select c.id,c.name,c.score,t.age,t.hobbid from test as t,class as c where t.name=c.name;
Query OK, 0 rows affected (0.00 sec)mysql> select * from v_stu;
+------+-------+--------+------+----------+
| id | name | score | age | hobbid |
+------+-------+--------+------+----------+
| 0002 | lizi | 100.00 | 18 | guangjie |
| 0003 | monor | 88.00 | 22 | zhaijia |
+------+-------+--------+------+----------+
2 rows in set (0.00 sec)#以class表的id,name,score和test表的age,hobbid字段,两表中名字相同的数据创建v_stu视图
查看视图
select * from 视图名;
mysql> select * from v_stu;
+------+-------+--------+------+----------+
| id | name | score | age | hobbid |
+------+-------+--------+------+----------+
| 0002 | lizi | 100.00 | 18 | guangjie |
| 0003 | monor | 88.00 | 22 | zhaijia |
+------+-------+--------+------+----------+
2 rows in set (0.00 sec)
查看表状态
show table status\G;
mysql> show table status\G;*************************** 4. row ***************************Name: v_stuEngine: NULLVersion: NULLRow_format: NULLRows: NULLAvg_row_length: NULLData_length: NULL
Max_data_length: NULLIndex_length: NULLData_free: NULLAuto_increment: NULLCreate_time: NULLUpdate_time: NULLCheck_time: NULLCollation: NULLChecksum: NULLCreate_options: NULLComment: VIEW
4 rows in set (0.00 sec)ERROR:
No query specified#可以看到,视图的表结构都为空,可以防止结构暴露带来的危害#当然本机用 desc 视图名; 还是可以查看的
查看视图与源表结构
desc 视图名;
desc 表名;
mysql> desc v_stu;
+--------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| id | int(4) unsigned zerofill | NO | | NULL | |
| name | char(10) | YES | | NULL | |
| score | decimal(5,2) | YES | | NULL | |
| age | int(3) | YES | | NULL | |
| hobbid | varchar(80) | YES | | NULL | |
+--------+--------------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)mysql> desc class;
+---------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------------------+------+-----+---------+-------+
| id | int(4) unsigned zerofill | NO | PRI | NULL | |
| name | char(10) | YES | | NULL | |
| score | decimal(5,2) | YES | | NULL | |
| address | varchar(80) | YES | | NULL | |
| course | char(10) | YES | | NULL | |
+---------+--------------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)mysql> desc test;
+--------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| idcard | int(2) unsigned zerofill | NO | | NULL | |
| name | char(10) | YES | | NULL | |
| age | int(3) | YES | | NULL | |
| hobbid | varchar(80) | YES | | NULL | |
+--------+--------------------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
单表创建视图
create view 视图名 as select 字段1,字段2,... from 表名 where 列名 取值范围;
mysql> create view v_class as select id,name,score from class where score>=80;
Query OK, 0 rows affected (0.00 sec)mysql> select * from v_class;
+------+-------+--------+
| id | name | score |
+------+-------+--------+
| 0002 | lizi | 100.00 |
| 0003 | monor | 88.00 |
+------+-------+--------+
2 rows in set (0.00 sec)
修改源表数据看视图
修改视图数据看源表
修改表不能修改以函数、复合函数方式计算出来的字段
视图查询方便、安全;索引速度快,多表查询更快(视图不保存真实数据,本质类似于select查看的快捷方式);视图对外无法显示完整的约束,更安全
删除视图
drop view 视图名;
七、null值
通常使用null来表示缺失的值,表示该字段没有值;
NULL 值与数字 0 或者空白(spaces)的字段是不同的,值为 NULL 的字段是没有值的。
在 SQL 语句中,使用 IS NULL 可以判断表内的某个字段是不是 NULL 值,相反的用 IS NOT NULL 可以判断不是 NULL 值。
null值、0、空值的区别
空值长度为0,不占空间;NULL值的长度为null,占用空间
is null 可以判断是否为null值;无法判断空值
空值使用 "=" 或者 "< >" 来处理(!=)
count() 计算时,null会被忽略,空值会加入计算
插入一条数据,分数字段输入null,显示出来的就是null
insert into class values(8,'aaa',null,'hangzhou',7);
insert into class (id,name) values(9,'bbb');
统计数量:检测null值是否会加入统计
select count(address) from class;
select count(score) from class;
检测null是否会加入统计中
update class set name='' where name='qiqi';
查询null值
查询不为空的值
八、连接查询★★★
mysql的连接查询,通过共同字段将两个或多个表的记录行进行数据拼接;
确定一个主表作为结果集,然后将其他表的行有选择性的连接到选定的主表结果集上;
使用较多的连接查询包括:内连接、左连接和右连接
生产环境中,对表的查询一般涉及一个或两个表,不会超多三个表;涉及过多的表说明表的字段分布不合理,需要优化;而且多表查询时要扫描多个表占用大量系统资源,造成卡顿
模板
mysql> select * from class;
+------+--------+-------+----------+--------+
| id | name | score | address | course |
+------+--------+-------+----------+--------+
| 0001 | yiyi | 78.00 | shanghai | 1 |
| 0002 | lizi | 92.00 | henan | 1 |
| 0003 | monor | 88.00 | nanjing | 2 |
| 0004 | sisi | 60.00 | nanjing | 3 |
| 0005 | wuwu | 37.00 | shanghai | 3 |
| 0006 | liuliu | 66.00 | henan | 2 |
| 0007 | qiqi | 13.00 | hangzhou | 4 |
+------+--------+-------+----------+--------+
7 rows in set (0.00 sec)mysql> select * from test;
+--------+--------+------+----------+
| idcard | name | age | hobbid |
+--------+--------+------+----------+
| 01 | lizi | 18 | guangjie |
| 02 | monor | 22 | zhaijia |
| 03 | sansan | 9 | wan |
+--------+--------+------+----------+
3 rows in set (0.00 sec)
1、内连接
mysql 中的内连接:两张或多张表中同时符合某种条件的数据记录的组合;
通常在 from 子句中使用关键字 inner join 来连接多张表,并使用 on 子句设置连接条件;
内连接是系统默认的表连接,所以在 from 子句后可以省略 inner 只使用 join ;
可以通过连续使用 inner join 来实现多表的内连接,最好不要超过三个表
内连接必须要有共同字段,才能做内连接查询
语法:
select * from 表1 inner join 表2 on 表1.字段=表2.字段;
例:
select * from class c inner join test t on c.name=t.name;
通过内连接来显示test 表和class 表中name相同的数据
2、左连接
左连接,又叫左外连接;在from子句中使用left join 或者left outer join 关键字来表示
左连接以左侧表为基础表,匹配左表中的所有行以及右表中符合条件的行
select * from 表1 left join 表2 on 表1.name=表2.name;
select * from class c left join test t on c.name=t.name;
在左连接的查询结果集中,除了符合匹配规则的行外,还包括左表中有但是右表中不匹配的行,这些记录在右表中以 NULL 补足
3、右连接
右连接也被称为右外连接;
在 from 子句中使用 right join 或者 right outer join 关键字来表示;
右连接跟左连接正好相反,以右表为基础表,匹配右表中的所有行以及左表中符合条件的行
select * from 表1 right join 表2 on 表1.name=表2.name;
select * from class c right join test t on c.name=t.name;
在右连接的查询结果集中,除了符合匹配规则的行外,还包括右表中有但是左表中不匹配的行,这些记录在左表中以 NULL 补足
九、存储过程★★★
存储过程通过使用多条SQL语句可以轻松高效的处理数据库的复杂操作;
类似shell脚本里的函数
1、存储过程是一组为了完成特定功能的SQL语句集合;
有两个关键点:触发器(定时任务) 和 判断
2、存储过程这个功能是从5.0版本才开始支持的,可以加快数据库的处理速度,增强数据库在实际应用中的灵活性。
存储过程是预先将sql语句写好并指定名称存储起来,经过编译和优化后存储到数据库服务器中;
使用时可以直接调用;存储过程相比传统的sql语句,执行速度更快、效率更高
存储过程在数据库中创建并保存,它不仅仅是 SQL语句的集合,还可以加入一些特殊的控制结构,也可以控制数据的访问方式。存储过程的应用范围很广,例如封装特定的功能、 在不同的应用程序或平台上执行相同的函数等等。
1.存储过程的优点
执行一次后,会将生成的二进制代码驻留到缓冲区,提高执行效率
sql语句加上控制语句的集合,灵活性高
在服务端存储,客户端调用时,可以降低网路负载
可以多次重复被调用,可以随时修改,不影响客户端调用
可完成所有的数据库操作,也可控制数据库的信息访问权限
语法
#将语句的结束符号从分号;临时改为两个$$(可以自定义)
mysql> delimiter $$
#创建存储过程,配置过程名和参数
mysql> create procedure 过程名(参数)
#过程体以关键字 begin 开始-> begin
#过程体语句-> -> ->
#过程体以关键字 end 结束-> end $$#将语句的结束符号恢复为分号
delimiter ;
创建存储过程
存储过程的主体都分,被称为过程体
以BEGIN开始,以END结束,若只有一条SQL语句,则可以省略BEGIN-END
以DELIMITER开始和结束
mysgl>DEL工M工TER $$ $$是用户自定义的结束符
省略存储过程其他步骤
mysql>DELIMITER ; 分号前有空格
#将语句的结束符号从分号;临时改为两个$$(可以自定义)
mysql> delimiter $$
#创建存储过程,过程名为class,不带参数
mysql> create procedure class()
#过程体以关键字 begin 开始-> begin
#过程体语句-> create table if not exists class (id int(2) zerofill not null,name char(10),score decimal(5,2));-> insert into class values(1,'yiyi',95);-> insert into class values(2,'erer',75);-> insert into class values(3,'sansan',55);-> select * from class;
#过程体以关键字 end 结束-> end $$
Query OK, 0 rows affected (0.02 sec)
#将语句的结束符号恢复为分号
delimiter;
调用存储过程
call 存储名;
查看存储过程
show create procedure 存储过程名\G;
查看所有存储过程信息
show procedure status\G;
查看指定存储过程信息
show procedure status like '%存储过程名%'\G;
show procedure status like '%class%'\G;
存储过程的参
in 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
out 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
inout 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
mysql> delimiter //
mysql> create procedure class1 (in inname varchar(20))-> begin-> select * from class where name=inname;-> end //
Query OK, 0 rows affected (0.01 sec)mysql> delimiter ;
mysql> select * from class1;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 01 | yiyi | 95.00 |
| 02 | erer | 75.00 |
| 03 | sansan | 55.00 |
+----+--------+-------+
3 rows in set (0.00 sec)mysql> call test('sansan');
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 03 | sansan | 55.00 |
+----+--------+-------+
1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)mysql>
修改存储过程
适用于当只修改1、2条过程体时;当修改涉及到大量过程体时建议直接删除重建
ALTER PROCEDURE <过程名>[<特征>... ]
ALTER PROCEDURE GetRole MODIFIES SQL DATA SQL SECURITY INVOKER;
MODIFIES sQLDATA:表明子程序包含写数据的语句
SECURITY:安全等级
invoker:当定义为INVOKER时,只要执行者有执行权限,就可以成功执行。
删除存储过程
存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。
drop procedure if exists 存储过程名;
drop procedure if exists class;