新手小白学MySQL

新手小白学MySQL

  • 记住:DQL语句中的执行顺序
  • DB、DBMS、SQL的关系
  • 表table
  • SQL语句的分类
  • 导入初始化数据
  • SQL脚本: xx.sql,可以使用source命令来执行此脚本
  • MYSQL常用命令
    • 创建数据库 create database 库名;
    • 使用数据库 use 库名;
    • 查询当前使用的数据库 select database();
    • 终止一条语句:\c
    • 查看其它库中的表:show tables from 其它库名;
    • 查看表结构:desc 表名;
    • 查看表的创建语句: show create table 表名;
  • SQL语句
    • 提示:sql语句的注意事项
    • 简单查询语句DQL:select 字段名1,字段名2,....from 表名;
    • 甚至as 可以省略!
      • 注意:实际开发中,我们要用java开发,因此不能用select * 查询,仅供自己查询时使用即可
    • 条件查询:select 字段 from表名 where 条件;(先执行from,再执行where,最后执行select)包括:=,<>,<,>,<=,>=,between and, is null, is not null, and, or, in, not, like
    • 注意:between and 用在数字,可以看做是闭区间;用在字符上,是左闭右开区间
      • and 和 or的联合使用:and的优先级高,因此当sql语句中同时出现and和or时,会先执行and,因此为了业务逻辑正确,可以使用小括号
      • in有点等同于or,比如之前的select ename , job from emp where job = 'manager' or job = 'salesman';等同于select ename, job from emp where job in ('manager' , ' salesman');
      • 模糊查询like中两个特殊的符号:%和下划线_;其中%:代表任意多个字符;_代表任意一个字符
    • 排序(升序asc(默认)、降序desc)order by
      • 注意:越靠前的字段,越能起到主导作用,只有当前面的字段无法完成排序时,才会启用后面的字段
      • 注意:还可以指定按照第几列的字段进行排序(不建议使用,java中不能用)
      • 注意:from/where/order by 同时使用时,先执行from,再执行where,最后是order by
  • 分组函数(count,sum,avg,max,min),又称多行处理函数:对某一组数据进行操作;多行输入,单行输出
      • count(某一字段)和count(*)的区别
      • 分组函数也可以组合在一起使用
    • 注意:分组函数会自动忽略null
  • 单行处理函数:单行输入,单行输出
    • 规定:所有数据库都规定,只要有null所参与的运算,其结果一定为null!!!!
    • null参与运算的处理:ifnull()函数:空处理函数,属于单行处理函数
  • group by (按照某个或者某些字段分组) 和 having(对分组后的数据进行再一次过滤)
    • 注意:group by 一般都会和分组函数联合使用。且先执行group by,后执行分组函数。
    • 如果sql语句中没有group by,那么整张表会自成一组。(即可缺省)
    • 因此这也能解释为什么分组函数不能出现在where子句中,因为:group by在where子句之后执行,而分组函数在group by之后执行。
      • 注意:select ename , job ,max(sal) from emp group by job;在mysql中可以执行,但是其结果毫无意义,因为在表中ename有14个字段,而按照工作岗位分组之后只有4个,这样一来ename和分组后的数据对应不上,输出的结果毫无意义。此外,在oracle数据库中执行此sql语句肯定会报错的。
    • 结论:当sql语句含有group by时,只允许select后面出现分组函数以及参与分组的字段。
    • 查询结果集的去重distinct关键字
      • 注意:distinct只能出现在所有字段的最前方,用于将后面所选的所有字段全部去重
  • 总结一个完整DQL语句的编写
  • 连接查询:从多张表中联合查询,取出最终的查询结果
    • 连接查询的分类:内连接/外连接/全连接
    • 笛卡尔积现象:当两张表连接查询,如果不加任何条件限制,最终查询结果条数会是两张表记录条数的乘积
    • 如何避免笛卡尔积现象
    • 内连接之等值连接:最大特点:条件是等量关系
    • 内连接之非等值连接:连接条件中的关系是非等量关系
    • 内连接之自连接:一张表看成两张表
    • 外连接
      • 注意:以上的left join和right join,都缺省了outer一词,严格意义上,应该是left outer join 和 right outer join,类似于内连接中join严格意义上应该是inner join。
    • 全连接(极少用):既使用左连接,又使用右连接
    • 三张及以上表的连接查询
    • 子查询
      • where后面嵌套子查询
      • from后面嵌套子查询
      • select后面嵌套子查询
  • union:可以将查询结果集相加
    • limit(重点!!!):mysql特有的语法(Oracle中有一个相同机制,叫做rownum)
    • 注意:limit是sql语句最后执行的语句
    • 通用的标准分页SQL
  • 表的创建
    • mysql中常见的字段数据类型:int ,bigint , float ,char , varchar, date, BLOB, CLOB
    • char(定长)和varchar(不定长)的选择:当某个字段的长度不发生改变时,是定长的,如性别生日等用char;当字段长度不确定,如姓名,用varchar
    • BLOB和CLOB类型的使用
      • 注意:BLOB不能用insert语句直接插入,只能用java中IO流这种形式进行插入。其他的类型如int,char等都可以使用insert插入
      • 建议:建表时,建议以t_或者tbl_开始,见名知意
  • 插入数据insert
      • 我们可以在建表时手动配置默认值的情况:
      • 倘若我们想插入数据时,把表中的所有字段都手动赋值,那么此时可以省略table后面跟的小括号以及里面的字段名,但是在values后面赋的值必须要和默认字段名的顺序一一对应:
      • 还可以一次插入多条数据:
    • 表的复制
    • 将查询结果插入到一张表中
  • 修改表中数据:update
  • 删除数据:delete
    • 如果要删除的表的数据十分庞大,如何快速删除表中数据?(重点)truncate(表被截断,不可回滚,永久丢失,谨慎操作!!!)
  • 对于表结构的修改(alter):在实际开发中很少发生,建议使用navicat等工具手动改即可
  • 约束Constraint:
    • 什么是约束及作用
    • 常见的约束:非空约束(not null)、唯一约束(unique)、主键约束(primary key)、外键约束(foreign key)、检查约束(check)(检查约束mysql没有,oracle有)
    • 非空约束 not null
    • 唯一性约束 unique:其修饰的字段具有唯一性,不能重复。但是可以为null。
      • 注意:设置唯一性约束的字段具有唯一性,但是可以多个记录的同一个字段的值为null
      • 如何给多个字段(列)添加unique:即不能多个字段同时相同
    • 主键约束 primary key
      • 如何添加主键约束
      • 因此,根据以上测试可以得出:主键中的数据不能为null,也不能重复
      • 主键的作用
      • 主键的分类:单一主键和复合主键,自然主键和业务主键
      • 主键表级约束的添加:auto_increment,这是mysql提供的!!!!!!(oracle也提供自增,叫做序列sequence)
    • 外键约束foreign key
      • 注意:外键是可以为null的
      • 注意:外键字段引用其他表的某个字段时,被引用的字段必须是主键吗?
  • 存储引擎:即表的存储方式
    • 常见存储引擎(mysql特有的名字,在oracle中就叫做存储方式)mysql默认使用InnoDB
      • myISAM存储引擎:不支持事务,但是省空间
      • InnoDB存储引擎:mysql默认的存储引擎,安全性高
      • MEMORY存储引擎:存储在内存,数据易丢失,查询快
  • 事务:只有DML语句(insert/delete/update)与事务相关,若不设置,默认一条语句是一个事务
    • 事务的四大特性ACID:原子性、一致性、隔离性、持久性
      • 隔离性:存在4个隔离级别,oracle默认级别是读已提交,mysql默认级别是可重复读。
    • 事务的演示
    • 演示隔离级别
  • 索引index:主键和具有unique约束的字段会自动添加索引
    • 什么是索引以及索引的作用
    • 何时需要添加索引
    • 如何添加和删除索引
    • 索引底层采用的数据结构:B+树
    • 索引的分类:单一索引、复合索引、主键索引、唯一索引
    • 索引在何时会失效:模糊查询(like)时,第一个通配符是%时,索引会失效。
  • 视图view
    • 创建和删除视图
    • 对视图进行增删改查,会影响原表数据
    • 视图的作用
  • DBA命令:主要是数据库数据的导入导出
    • 新建用户
    • 授权
    • 撤销权限
    • 导入导出数据
      • 导出
      • 导入
  • 数据库设计三范式(重点!!!!):为了解决数据冗余
    • 第一范式
    • 第二范式:多对多的关系,三张表,关系表,两外键
    • 第三范式:一对多,两张表,多的表加外键
    • 一对一怎么设计:两种方案1.主键共享2.外键唯一
  • 总结 表的设计:一对一,一对多,多对多
  • 作业题
  • 学习视频参考:B站MySQL从入门到精通视频教程 链接:https://www.bilibili.com/video/BV1fx411X7BD?p=1

记住:DQL语句中的执行顺序

新手小白学MySQL_第1张图片
分组函数的执行在group by(可缺省)之后。

DB、DBMS、SQL的关系

新手小白学MySQL_第2张图片

表table

新手小白学MySQL_第3张图片

SQL语句的分类

在这里插入图片描述

导入初始化数据

新手小白学MySQL_第4张图片
新手小白学MySQL_第5张图片

SQL脚本: xx.sql,可以使用source命令来执行此脚本

在这里插入图片描述

MYSQL常用命令

创建数据库 create database 库名;

使用数据库 use 库名;

查询当前使用的数据库 select database();

终止一条语句:\c

新手小白学MySQL_第6张图片

查看其它库中的表:show tables from 其它库名;

查看表结构:desc 表名;

在这里插入图片描述

查看表的创建语句: show create table 表名;

SQL语句

提示:sql语句的注意事项

简单查询语句DQL:select 字段名1,字段名2,…from 表名;

比如:查询员工年薪(字段可以参与数学运算):
新手小白学MySQL_第7张图片
再比如把年薪的查询结果那个字段重命名为年薪yearsal:
新手小白学MySQL_第8张图片
若想用中文年薪,那必须在年薪上加单引号:‘年薪’
新手小白学MySQL_第9张图片

甚至as 可以省略!

新手小白学MySQL_第10张图片

注意:实际开发中,我们要用java开发,因此不能用select * 查询,仅供自己查询时使用即可

查询全部字段:select * from 表名;
新手小白学MySQL_第11张图片
在这里插入图片描述

条件查询:select 字段 from表名 where 条件;(先执行from,再执行where,最后执行select)包括:=,<>,<,>,<=,>=,between and, is null, is not null, and, or, in, not, like

新手小白学MySQL_第12张图片
查询工资为5K的员工姓名:
在这里插入图片描述
查询名字为SMITH员工的工资(注意字符串类型(varchar)查询要加单引号‘ ’):
新手小白学MySQL_第13张图片
找出工资大于3k的员工:
在这里插入图片描述
找出工资不等于3k的员工(不等于为:<>):
select ename from emp where sal <> 3000;
新手小白学MySQL_第14张图片
找出工资在1100和3000之间的员工:
select enma ,sal from emp where sal>=1100 and sal <= 3000;
或者:
select ename , sal from emp where sal between 1100 and 3000;
但是注意:between and中的这两个数据,大小不能颠倒,前小后大,否则会找不到数据。。。
新手小白学MySQL_第15张图片
新手小白学MySQL_第16张图片
在这里插入图片描述

注意:between and 用在数字,可以看做是闭区间;用在字符上,是左闭右开区间

查询名字在between ‘A’ and 'C’的员工:
select ename from emp where ename between ‘A’ and ‘C’;
新手小白学MySQL_第17张图片
查询名字在between ‘A’ and 'D’的员工:
select ename from emp where ename between ‘A’ and ‘D’;
新手小白学MySQL_第18张图片
找出哪些津贴为空(不是为0,是null)的员工:
select ename from emp where comm is null;
新手小白学MySQL_第19张图片
找出津贴为0的员工:
select ename from emp where comm = 0;
在这里插入图片描述
找出津贴为null以及为0的员工:
select ename from emp where comm is null and comm = 0;
新手小白学MySQL_第20张图片
找出津贴不为null以及为0的员工:
select ename from emp where comm is not null;
新手小白学MySQL_第21张图片
找出工作岗位为manager和salesman的员工:
select ename , job from emp where job = ‘manager’ or job = ‘salesman’;
在这里插入图片描述

and 和 or的联合使用:and的优先级高,因此当sql语句中同时出现and和or时,会先执行and,因此为了业务逻辑正确,可以使用小括号

找出薪资大于1000并且部门编号为20或者30部门的员工:
select ename , sal, deptno from emp where sal > 1000 and (deptno = 20 or deptno = 30);
新手小白学MySQL_第22张图片

in有点等同于or,比如之前的select ename , job from emp where job = ‘manager’ or job = ‘salesman’;等同于select ename, job from emp where job in (‘manager’ , ’ salesman’);

新手小白学MySQL_第23张图片

模糊查询like中两个特殊的符号:%和下划线_;其中%:代表任意多个字符;_代表任意一个字符

找出名字中含有o的员工:
select ename from emp where ename like ‘%o%’;
新手小白学MySQL_第24张图片
找出名字中第二个字母是A的员工:
select ename from emp where ename like ‘_A%’;
新手小白学MySQL_第25张图片
找出名字带有下划线_的员工:使用转义字符\来表示:
select ename from emp where ename like ‘%_%’;
在这里插入图片描述

排序(升序asc(默认)、降序desc)order by

按照工资升序,找出员工名和薪资:
select ename , sal from emp order by sal;
新手小白学MySQL_第26张图片
按照工资降序,找出员工名和薪资:
select ename , sal from emp order by sal desc;
新手小白学MySQL_第27张图片

注意:越靠前的字段,越能起到主导作用,只有当前面的字段无法完成排序时,才会启用后面的字段

按照工资降序排列,当工资相同时,按照名字升序排列:
select ename , sal from emp order by sal desc , ename asc;
新手小白学MySQL_第28张图片

注意:还可以指定按照第几列的字段进行排序(不建议使用,java中不能用)

按照第二列的大小进行排序:
select ename , sal from emp order by 2;
新手小白学MySQL_第29张图片

注意:from/where/order by 同时使用时,先执行from,再执行where,最后是order by

找出工作岗位是salesman,并且要求薪资按照降序排列:
select ename ,job , sal from emp where job = ‘salesman’ order by sal desc;
新手小白学MySQL_第30张图片

分组函数(count,sum,avg,max,min),又称多行处理函数:对某一组数据进行操作;多行输入,单行输出

新手小白学MySQL_第31张图片
新手小白学MySQL_第32张图片
新手小白学MySQL_第33张图片
找出工资高于平均公司的员工:
错误范例:
select ename , sal from emp where sal >avg(sal);
###注意 :SQL语句的语法规则中,分组函数不可以直接使用在where子句中,因此上述代码出错。
正确格式:
方案一:可以分成两步:首先求出平均,然后sal>平均sal即可
新手小白学MySQL_第34张图片
方案二:即将上述两步合并即可(语句的嵌套,又称为子查询)
select ename ,sal from emp where sal >(select avg(sal) from emp );
新手小白学MySQL_第35张图片

count(某一字段)和count(*)的区别

具体到某个字段,count记录的是该字段不为空的记录数;
而count(*),统计的是总记录条数,与具体的某个字段无关。

分组函数也可以组合在一起使用

比如:
select count(*) , sum(sal) , avg(sal) , min(sal) , max(sal) from emp;
新手小白学MySQL_第36张图片

注意:分组函数会自动忽略null

select count(comm) from emp;
在这里插入图片描述

单行处理函数:单行输入,单行输出

规定:所有数据库都规定,只要有null所参与的运算,其结果一定为null!!!!

比如计算每个员工的年薪(月薪+月补助相加再乘12):
select ename , (sal + comm) * 12 as yearsal from emp;
新手小白学MySQL_第37张图片

null参与运算的处理:ifnull()函数:空处理函数,属于单行处理函数

仍以上述的计算每个员工的年薪(月薪+月补助相加再乘12):
select ename , (sal + ifnull(comm,0) * 12) as yearsal from emp;
新手小白学MySQL_第38张图片
如果使用ifnull,此时再次对comm进行计数:
select count( ifnull(comm , 0) ) from emp;
新手小白学MySQL_第39张图片

group by (按照某个或者某些字段分组) 和 having(对分组后的数据进行再一次过滤)

注意:group by 一般都会和分组函数联合使用。且先执行group by,后执行分组函数。

如果sql语句中没有group by,那么整张表会自成一组。(即可缺省)

因此这也能解释为什么分组函数不能出现在where子句中,因为:group by在where子句之后执行,而分组函数在group by之后执行。

比如找出每个工作岗位的最高薪资:
错误范例:
select ename, sal group by ‘salesman’ having max(sal);
正确代码:
select job, max(sal) from emp group by job;
新手小白学MySQL_第40张图片
错误示例:

注意:select ename , job ,max(sal) from emp group by job;在mysql中可以执行,但是其结果毫无意义,因为在表中ename有14个字段,而按照工作岗位分组之后只有4个,这样一来ename和分组后的数据对应不上,输出的结果毫无意义。此外,在oracle数据库中执行此sql语句肯定会报错的。

新手小白学MySQL_第41张图片
但实际上:SMITH的工资是800块
新手小白学MySQL_第42张图片

结论:当sql语句含有group by时,只允许select后面出现分组函数以及参与分组的字段。

每个工作岗位的平均薪资:
select job , avg(sal) from emp group by job;
新手小白学MySQL_第43张图片
找出每个部门不同工作岗位的最高薪资:
select max(sal), job , deptno from emp group by deptno , job;
新手小白学MySQL_第44张图片
找出每个部门的最高薪资,同时要求显示薪资大于2500的数据:
方式一:select ename, max(sal) from emp group by deptno having max(sal) > 2500;
但是这种效率比较低
新手小白学MySQL_第45张图片
方式二:
select deptno , max(sal) from emp where sal > 2900 group by deptno;
这种方式相比第一种效率高,因为先过滤掉sal>2900的,再按照部门求;而第一种先求出各个部门的最高薪资,然后部门编号30的因为最高薪资2850小于2900被过滤掉了,那么寻找部门编号30的最高薪资的工作相当于白干了。
新手小白学MySQL_第46张图片
找出每个部门的平均薪资,要求显示薪资大于2000的数据:
错误范例:
select deptno, avg(sal) from emp where (select avg(sal) from emp) > 2000 group by deptno;
新手小白学MySQL_第47张图片
以上并没有把小于2000的过滤掉,why???

正确代码:
select deptno, avg(sal) from emp group by deptno having avg(sal) >2000;
新手小白学MySQL_第48张图片

查询结果集的去重distinct关键字

比如:
查询公司的工作岗位:
select distinct job from emp;
新手小白学MySQL_第49张图片

注意:distinct只能出现在所有字段的最前方,用于将后面所选的所有字段全部去重

比如:
select ename, distinct job from emp;
会报语法错误。从逻辑上也很好分析:distinct去重之后,剩下的job岗位(5个)肯定少于表中的总记录数14条,而ename是公司每个员工的记录表,14名员工的ename和5种工作岗位是无法在表中正确显示的。
在这里插入图片描述
再比如:
select distinct deptno , job from emp;
新手小白学MySQL_第50张图片
统计岗位的数量:
select count(distinct job) from emp;
在这里插入图片描述

总结一个完整DQL语句的编写

新手小白学MySQL_第51张图片

连接查询:从多张表中联合查询,取出最终的查询结果

连接查询的分类:内连接/外连接/全连接

新手小白学MySQL_第52张图片

笛卡尔积现象:当两张表连接查询,如果不加任何条件限制,最终查询结果条数会是两张表记录条数的乘积

比如:
select ename , dname from emp , dept;或者
select e.ename , d,dname from emp as e, dept as d;(结果一样,只是可读性和执行效率提高了)
新手小白学MySQL_第53张图片
表长完整图略

如何避免笛卡尔积现象

注意:避免了笛卡尔积现象,并不会减少记录的匹配次数,只是输出的结果少了(因为通过添加限制,得出我们想要的有效记录,去除无效或者无用的记录)
找出每一个员工的部门名称,要求显示员工名和部门名:
方法一(sql92旧方法):

select
	e.ename , d.dname
from
	emp as e , dept as d
where e.deptno = d.deptno;

新手小白学MySQL_第54张图片

内连接之等值连接:最大特点:条件是等量关系

方法二(sql99常用):主要是把连接条件和过滤条件分开了,连接条件用join on,过滤条件用where,更加清晰

select
	e.ename , d.dname
from
	emp as e
join
	dept as d
on
	e.deptno = d.deptno;

新手小白学MySQL_第55张图片
新手小白学MySQL_第56张图片

内连接之非等值连接:连接条件中的关系是非等量关系

找出每个员工的工资等级,要求显示员工名、工资、工资等级:

select
	e.ename,e.sal,s.grade
from 
	emp as e
inner join
	salgrade as s
on
	e.sal between s.losal and s.hisal;

在这里插入图片描述

内连接之自连接:一张表看成两张表

找出每个员工的上级领导,要求显示员工名和对应的领导命:
即在同一张emp表中进行查找,但是在第一张表中所有人都是员工,在第二张表中全为领导,然后进行联合查询

select
	e1.name ,e2.name
from
	emp as e1
inner join
	emp as e2
on
	e1.mgr = e.empno; 

新手小白学MySQL_第57张图片
更清晰一点:

select
	e1.name as '员工名' ,e2.name as  '领导名'
from
	emp as e1
inner join
	emp as e2
on
	e1.mgr = e.empno; 

新手小白学MySQL_第58张图片

外连接

新手小白学MySQL_第59张图片
仍以上面的那额查询出所有员工的上级领导(要求所有员工都查到,包括那个KING),此时用左外连接(以e1员工表作为主表):

select
	e1.name as '员工名' ,e2.name as  '领导名'
from
	emp as e1
left join
	emp as e2
on
	e1.mgr = e.empno; 

新手小白学MySQL_第60张图片
此时,即使KING没有上级领导,但是同样输出了。
也可以用右外连接:

select
	e1.name as '员工名' ,e2.name as  '领导名'
from
	emp as e2
right join
	emp as e1
on
	e1.mgr = e.empno; 

这里的左和右,其实就是为了确定将哪个表作为主表。

注意:以上的left join和right join,都缺省了outer一词,严格意义上,应该是left outer join 和 right outer join,类似于内连接中join严格意义上应该是inner join。

找出哪个部门没有员工:
错误范例:
select d.dname , count(e.ename) from dept as d left join emp as e where e.deptno = d.deptno;
正确代码:

select
	d.*
from 
	dept as d
left join
	emp as e
on
	e.deptno = d.deptno
where
	e,ename is null;

新手小白学MySQL_第61张图片
也可以加上统计的员工数目:

select
	d.* , count(e.ename)
from 
	dept as d
left join
	emp as e
on
	e.deptno = d.deptno
where
	e,ename is null;

新手小白学MySQL_第62张图片

全连接(极少用):既使用左连接,又使用右连接

三张及以上表的连接查询

找出每名员工的部门名称以及员工等级:
先找出员工的部门名称:
select e.name , e.empno , e.deptno from emp e left join dept d where e.deptno = d.deptno;
新手小白学MySQL_第63张图片
再找出每名员工的员工等级:
select e.ename, e.empno ,e.deptno , s.grade from emp e left join salgrade s on e.sal between losal and hisal;
新手小白学MySQL_第64张图片
将二者结合一下:

select 
	e.ename , d.dname , s.grade
from
	emp e
join 
	dept d
on 
	e.deptno = d.deptno 
join
	salgrade s
on
	e.sal between s.losal and s.hisal;
	

新手小白学MySQL_第65张图片
找出每一个员工的部门名称,工资等级以及上级领导(由于emp中存在员工KING的上级领导是null的情况,因此为了保证输出结果中包括每一名员工,必须采用外连接):

select 
	e1.ename , e2.name , d.dname , s.grade
from
	emp e1
left join
	emp e2
on
	e1.mgr = e2.empno
join 
	dept d
on 
	e1.deptno = d.deptno 
join
	salgrade s
on
	e1.sal between s.losal and s.hisal;

新手小白学MySQL_第66张图片
其实可以在上一例子的后面直接添加:

select 
	e1.ename , d.dname , s.grade , e2.ename
from
	emp e1
join 
	dept d
on 
	e1.deptno = d.deptno 
join
	salgrade s
on
	e1.sal between s.losal and s.hisal
left join
	e1.mgr = e2.empno;

子查询

新手小白学MySQL_第67张图片

where后面嵌套子查询

之前讲过,如:找出薪资高于平均薪资的员工信息:
select * from emp where sal >(select avg(sal) from emp);

from后面嵌套子查询

找出每个部门平均薪水的薪资等级(这个没写出来):
首先:平均薪水:
select deptno , avg(sal) from emp group by deptno;
新手小白学MySQL_第68张图片然后将上一步的执行结果作为一个新表,进行查询:
错误范例(语法错误,a.avg不合法):
select a.deptno , a.avg(sal) , s.grade from (select deptno , avg(sal) from emp group by deptno) a , salgrade s where a.avg(sal) between s.losal and s.hisal;

正确代码:

select 
	t.* , s.grade
from
	(select deptno , avg(sal) as avgsal from emp group by deptno) as t
join
	salgrade as s
on
	t.avgsal between s.losal and s.hisal;

新手小白学MySQL_第69张图片

select后面嵌套子查询

找出每个员工做在的部门名称,要求显示员工名和部门名:
select e.ename , d.dname from emp e, dept d where e.deptno = d.deptno;
新手小白学MySQL_第70张图片
还可以使用嵌套子查询的方式:

select
	e.ename , (select d.dname from dept d where e.deptno = d.deptno) as dname
from
emp e;

union:可以将查询结果集相加

找出工作岗位是salesman和manager的员工:
方法一:select e.ename , e.job from emp e where e.job = ‘salesman’ or e.job = ‘manager’;
新手小白学MySQL_第71张图片
方法二:select ename, job from emp where job in (‘salesman’ , ‘manager’);
方法三:使用union

select ename , job from emp where job = 'salesman'
union
select ename , job from emp where job ='manager';

新手小白学MySQL_第72张图片

limit(重点!!!):mysql特有的语法(Oracle中有一个相同机制,叫做rownum)

取出工资前五名的员工(思路就是降序取出前5个):
select ename , sal , job from emp order by sal desc limit 0 , 5;
新手小白学MySQL_第73张图片
默认从0开始,如果从0开始查询,可以缺省0
新手小白学MySQL_第74张图片
找出工资排名第四名到第九名的员工:
select ename , job ,sal from emp order by sal desc limit 3,6;

新手小白学MySQL_第75张图片

注意:limit是sql语句最后执行的语句

新手小白学MySQL_第76张图片

通用的标准分页SQL

每页显示3条记录:
第1页:0,3
第2页:3,3
第3页:6,3
第4页:9,3
第5页:12,3

每页显示pageSize条记录:
第pageNo页:(pageNo-1)*pageSize , pageSize

表的创建

建表语句格式:

create table 表名(
	字段名1 数据类型,
	字段名2 数据类型,
	字段名3 数据类型,
	....
);

mysql中常见的字段数据类型:int ,bigint , float ,char , varchar, date, BLOB, CLOB

新手小白学MySQL_第77张图片

新手小白学MySQL_第78张图片
在这里插入图片描述

char(定长)和varchar(不定长)的选择:当某个字段的长度不发生改变时,是定长的,如性别生日等用char;当字段长度不确定,如姓名,用varchar

比如:出生日期:yyyy-mm-dd 标准10个长度 用char;性别:男/女,标准1个长度,用char;
比如:姓名:中文有两个字,有三个字,有四个字的,用varchar;

BLOB和CLOB类型的使用

在这里插入图片描述

注意:BLOB不能用insert语句直接插入,只能用java中IO流这种形式进行插入。其他的类型如int,char等都可以使用insert插入

建议:建表时,建议以t_或者tbl_开始,见名知意

创建学生表:
学生信息包括:学号(bigint)、姓名(varchar)、性别(char)、班级编号(varchar)、生日(char)

create table t_student(
	stuno bigint,
	name varchar(255),
	sex char(1),
	classno varchar(255),
	birthday char(10)
);

新手小白学MySQL_第79张图片
新手小白学MySQL_第80张图片

插入数据insert

语法格式:

insert into 表名(字段名1,字段名2,字段名3,...) values(1,2,3,...);

要求:字段的数量要和值的数量相同,并且数据类型要对应相同。
向学生信息表中插入数据:

insert into t_student(stuno , name , sex , classno , birthday) values(1 , 'ykk' , 'm' , 'gaosan0ban' , '2000-01-31');

新手小白学MySQL_第81张图片
也可以指给几个字段赋值,其他未赋值字段默认为null:

insert into t_student(stuno , name , sex) values(5, 'zhangsan' , 'f');

新手小白学MySQL_第82张图片
这是因为我们在创建表的时候,设置了各个字段的默认值(若不手动设置,会默认值为null):
新手小白学MySQL_第83张图片

我们可以在建表时手动配置默认值的情况:

create table t_student(
	stuno bigint,
	name varchar(255),
	sex char(1) default 'm',
	classno varchar(255),
	birthday char(10) default '1970-01-01'
);

新手小白学MySQL_第84张图片

此时再插入一个:

insert into t_student(stuno , name ) values(5, 'zhangsan');

新手小白学MySQL_第85张图片

倘若我们想插入数据时,把表中的所有字段都手动赋值,那么此时可以省略table后面跟的小括号以及里面的字段名,但是在values后面赋的值必须要和默认字段名的顺序一一对应:

比如:

insert into t_student values(2 , 'lisi' , 'f' , 'gaosan0ban' , '2000-01-24' );

新手小白学MySQL_第86张图片

还可以一次插入多条数据:

insert into t_student(stuno , name , sex , classno , birthday) values(10 , 'rose' , 'f' , 'Titanic' , '1975-10-23'),(11 , 'jack' , 'm' , 'Titanic' ,'1972-12-03');

新手小白学MySQL_第87张图片

表的复制

语法:

create table 表名 as select 语句;
//这里其实是将查询结果当做表创建出来

比如完全复制一张表:

create table emp1 as select * from emp;

新手小白学MySQL_第88张图片
再比如复制指定字段:

create table emp2 as select empno , ename from emp;

新手小白学MySQL_第89张图片

将查询结果插入到一张表中

比如我们先创建一张表:

create table dept1 as select * from dept;

新手小白学MySQL_第90张图片

再将dept表插入dept1中:

insert into dept1 select * from dept;

新手小白学MySQL_第91张图片

修改表中数据:update

语法格式:

update 表名 set 字段名1 =1, 字段名2 =2... where 条件;
// 倘若后面不加条件,整张表的数据都会全部更新

将dept1 表中部门编号为10 的LOC 修改为shanghai,将部门名称修改为renshibu:

update dept1 set LOC = 'SHANGHAI' , DNAME = 'RENSHIBU' where deptno = 10;

新手小白学MySQL_第92张图片
不加条件,更改全部表的信息:

update dept1 set LOC = 'BEIJING' , DNAME = 'YANFA'; 

新手小白学MySQL_第93张图片

删除数据:delete

语法格式:

delete from 表名 where 条件;

注意:不加条件,会删除整张表;
删除dept1表中部门10 的数据:

delete from dept1 where DEPTNO = 10;

新手小白学MySQL_第94张图片
不加条件,删除整张表的所有记录:

delete from dept1;

在这里插入图片描述

如果要删除的表的数据十分庞大,如何快速删除表中数据?(重点)truncate(表被截断,不可回滚,永久丢失,谨慎操作!!!)

truncate table 表名;

在这里插入图片描述

对于表结构的修改(alter):在实际开发中很少发生,建议使用navicat等工具手动改即可

约束Constraint:

新手小白学MySQL_第95张图片

什么是约束及作用

在创建表时,可以给表的字段添加相应的约束,其目的是为了保证表中数据的合法性、有效性、完整性。

常见的约束:非空约束(not null)、唯一约束(unique)、主键约束(primary key)、外键约束(foreign key)、检查约束(check)(检查约束mysql没有,oracle有)

非空约束 not null

先创建个表做测试:

create table t_users(
	id int ,
	username varchar(255) not null ,
	password carchar(255) 
);

此时,给username字段添加了非空约束,我们此时插入一条数据:

insert into t_user(id , password) values(1 , '123'); 

在这里插入图片描述
新手小白学MySQL_第96张图片
因此,设置了非空约束的字段,插入时必须要赋值,不能为null。

唯一性约束 unique:其修饰的字段具有唯一性,不能重复。但是可以为null。

新建一个用户表,要求用户名字段不能重复(即要求有唯一性):

create table u_users(
	id int ,
	username varchar(255)  unique,
	password varchar(255)
);

然后向表中插入两条username均为jack的记录:

insert into t_users values(1, 'jack' ,'123');
insert into t_users values(2, 'jack' ,'456'); 

新手小白学MySQL_第97张图片

注意:设置唯一性约束的字段具有唯一性,但是可以多个记录的同一个字段的值为null

比如:
插入两条username为空的记录是允许的:

insert into t_users(id , password) values(2 , '456'),(2, '789');

新手小白学MySQL_第98张图片

如何给多个字段(列)添加unique:即不能多个字段同时相同

比如:不允许username和usercode都相同(要和既不允许username相同,又不允许usercode相同区别开):

create table t_users(
	id int ,
	username varchar(255),
	usercode varchar(255),
	unique(username , usercode)// 表级约束
);

此时,插入以下数据测试:

insert into t_users values(1 , '111' , 'zs');
insert into t_users values(2 , '111' , 'ww');
insert into t_users values(3 , '222' , 'zs');

新手小白学MySQL_第99张图片
是可以在username不同的前提下允许usercode重复,反之亦可;
即username和usercode联合起来不能重复。

而考虑如下情况:

create table t_users(
	id int ,
	username varchar(255) unique,// 列级约束
	usercode varchar(255) unique
);

此时再插入上例中的相同三条数据:

insert into t_users values(1 , '111' , 'zs');
insert into t_users values(2 , '111' , 'ww');
insert into t_users values(3 , '222' , 'zs');

新手小白学MySQL_第100张图片
此时,usercode字段值不允许重复,username字段值也不允许重复,即两个字段分别都不允许重复。

主键约束 primary key

如何添加主键约束

例:

create table t_users(
	id int primary key ,
	username varchar(255) ,
	password varchar(255)
);

插入3条数据:

insert into t_users values(1 , 'jack' , '123');
insert into t_users values(2, 'rose' , '456');
insert into t_users values(3 , 'ben' , '789');

新手小白学MySQL_第101张图片
此时,再插入以下数据,报错:

insert into t_users values(1 , 'simmons' , '321');

在这里插入图片描述
再插入以下数据,再次报错:

insert into t_users( username , password) values( 'simmons' , '321');

在这里插入图片描述

因此,根据以上测试可以得出:主键中的数据不能为null,也不能重复

主键的作用

在这里插入图片描述

主键的分类:单一主键和复合主键,自然主键和业务主键

新手小白学MySQL_第102张图片

主键表级约束的添加:auto_increment,这是mysql提供的!!!!!!(oracle也提供自增,叫做序列sequence)

create table t_user(
	id int primary key auto_increment , 
	username varchar(255)
);

不给主键赋值,插入数据:

insert into t_user( username ) values('jack');
insert into t_user( username ) values('rose');
insert into t_user( username ) values('jackson');
insert into t_user( username ) values('robin');

新手小白学MySQL_第103张图片
我们没有手动给主键赋值,主键从1开始,每次自增1。

外键约束foreign key

在数据库中如何维护班级和学生表?
第一种方案:将学号、姓名、班级代码、班级全称放在一张表中维护。
缺点:冗余。
第二种方案:
新手小白学MySQL_第104张图片
新手小白学MySQL_第105张图片
删表先删子表再删子:

drop if exists t_class;
drop if exists t_student;

建表先创建父表再创建子表:

create table t_class(
	cno int ,
	cname varchar(255) , 
	primary key(cno)
);
create table t_student(
	sno int , 
	sname varchar(255) , 
	classno int ,
	foreign key(classno) references t_class(cno)
);

新手小白学MySQL_第106张图片
新手小白学MySQL_第107张图片
插入数据,先插父表,再插入子表:

insert  into t_class values(101 , 'cs1001');
insert  into t_class values(102 , 'cs1002');
insert  into t_class values(103 , 'cs1003');

新手小白学MySQL_第108张图片

insert  into t_student values(18611 , 'jack' , 101);
insert  into t_student values(18522 , 'rose' , 102);
insert  into t_student values(18933, 'robin' , 103);

新手小白学MySQL_第109张图片
倘若在子表中插入外键对应父表字段中没有的值,会报错

insert  into t_student values(18844, 'ben' , 104);

在这里插入图片描述

注意:外键是可以为null的

insert  into t_student values(123678, 'sophia' , null);

新手小白学MySQL_第110张图片

注意:外键字段引用其他表的某个字段时,被引用的字段必须是主键吗?

在这里插入图片描述

存储引擎:即表的存储方式

指定存储引擎的完整的表语句:

create table t_x(
	id int default null
)ENGINE = InnoDB DEFAULT CHARSET = utf8;

mysql默认存储引擎是InnoDB,默认字符集CHARSET是utf8.

常见存储引擎(mysql特有的名字,在oracle中就叫做存储方式)mysql默认使用InnoDB

查看当前mysql使用的存储引擎:

show engines \G;

新手小白学MySQL_第111张图片
没有截全。

myISAM存储引擎:不支持事务,但是省空间

新手小白学MySQL_第112张图片
新手小白学MySQL_第113张图片

InnoDB存储引擎:mysql默认的存储引擎,安全性高

新手小白学MySQL_第114张图片
新手小白学MySQL_第115张图片
在这里插入图片描述

MEMORY存储引擎:存储在内存,数据易丢失,查询快

新手小白学MySQL_第116张图片
新手小白学MySQL_第117张图片

事务:只有DML语句(insert/delete/update)与事务相关,若不设置,默认一条语句是一个事务

新手小白学MySQL_第118张图片

事务的四大特性ACID:原子性、一致性、隔离性、持久性

新手小白学MySQL_第119张图片

隔离性:存在4个隔离级别,oracle默认级别是读已提交,mysql默认级别是可重复读。

新手小白学MySQL_第120张图片

事务的演示

演示1:mysql中的事务支持自动提交,只要执行一条DML语句,就会自动提交一次。
新手小白学MySQL_第121张图片
执行rollback并不能将插入的记录删除,说明插入username为john这条语句作为事务已经提交,因此不可回滚。
演示2:使用start transaction关闭自动提交机制(标志着事务执行的开始):

start transaction;

然后再插入数据:

insert into t_user(username) values('simmons');
insert into t_user(username) values('joe');

然后回滚rollback,查看此时的t_user表中记录:

新手小白学MySQL_第122张图片
此时,表中并没有joe与simmons的记录,说明回滚了。

演示隔离级别

设置事务的全局隔离级别


set global transaction isolation level 具体级别(包括read uncommitted , read committed , repeatable-read , serializable;

查看当前事务的全局隔离级别

select @@global.tx_isolation;

新手小白学MySQL_第123张图片

索引index:主键和具有unique约束的字段会自动添加索引

什么是索引以及索引的作用

新手小白学MySQL_第124张图片

何时需要添加索引

新手小白学MySQL_第125张图片

如何添加和删除索引

添加索引:

create index 索引名 on 表名(字段名);
例如:
create index emp_sal_index on emp(sal);

删除索引:

drop index 索引名 on 表名;
例如:
drop index emp_sal_index on emp;

索引底层采用的数据结构:B+树

新手小白学MySQL_第126张图片
新手小白学MySQL_第127张图片

索引的分类:单一索引、复合索引、主键索引、唯一索引

新手小白学MySQL_第128张图片

索引在何时会失效:模糊查询(like)时,第一个通配符是%时,索引会失效。

视图view

创建和删除视图

创建视图:

create view myview as select empno , ename from emp;
// 只有DQL语句才能以视图对象的方式创建出来。

删除视图:

drop view myview;

对视图进行增删改查,会影响原表数据

通过视图修改原表数据:

update myview set enam = 'hehe' , sal = 1 where empno = 7369;

通过视图删除原表数据:

delete from myview where empno = 7369 ;

视图的作用

在这里插入图片描述

DBA命令:主要是数据库数据的导入导出

新建用户

create user username(用户名) identified by password(密码);
//例如:
create user jack identified by 123;

授权

// grant to
grant all privileges on dbname , tbname  to 'username'@'login ip' identified by 'password' with grant option;
// 例如:
grant all privileges on *.* to 'jack'@localhost identified by '123';
//如果希望在任何机器登陆mysql,只需将localhost改为%

新手小白学MySQL_第129张图片

撤销权限

revoke privileges on dbname[.tbname] from username;
// 例如:
revoke all privileges on *.* from jack;

新手小白学MySQL_第130张图片

导入导出数据

导出

导出整个数据库:
在dos窗口下执行此命令(不要登入到mysql执行)

mysqldump 数据库名 >要导出的地址路径 -u用户名 -p密码;
// 例如:
mysqldump bjpowernode>D:bjpowernode.sql -uroot -p;

导出指定表:

mysqldump 数据库名 要导出的表名>要导出的路径 -u用户名 -p密码;
//例如:
mysqldump bjpowernode emp>D:bjpowernode.sql -uroot -p;

导入

先创建数据库:

create database bjpowernode;
use bjpowernode;

然后 source + 文件拖拽即可(或者sql文件绝对路径);

数据库设计三范式(重点!!!!):为了解决数据冗余

第一范式

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

第二范式:多对多的关系,三张表,关系表,两外键

建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖(只有复合主键才会存在部分依赖,单一主键不存在部分依赖)。
新手小白学MySQL_第131张图片

第三范式:一对多,两张表,多的表加外键

建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖。
新手小白学MySQL_第132张图片

一对一怎么设计:两种方案1.主键共享2.外键唯一

新手小白学MySQL_第133张图片
新手小白学MySQL_第134张图片

总结 表的设计:一对一,一对多,多对多

作业题

1.取得每个部门薪水最高的人员名称
错误示范:

select ename , deptno , max(sal) from emp group by deptno;

新手小白学MySQL_第135张图片
正确代码:

// 第一步 先取出各个部门的最高薪水
select deptno , max(sal) as maxsal from emp group by deptno;
// 第二步 
select 
	e.ename , t.* 
from
	(select deptno , max(sal) as maxsal from emp group by deptno) t
join
	emp e
on
	t.deptno = e.deptno and t.maxsal = e.sal;

新手小白学MySQL_第136张图片

学习视频参考:B站MySQL从入门到精通视频教程 链接:https://www.bilibili.com/video/BV1fx411X7BD?p=1

你可能感兴趣的:(mysql,数据库,oracle)