MYSQL(老杜数据库笔记)

 1.卸载MYSQL

  • mysql-5.5.36-win32 (1).msi进去remove
  • 找到C盘下的program files(x86)目录进去把MYSQL目录删除然后把隐藏目录programData下MYSQL删除

2.数据库登录

  1. 命令提示符要以管理员身份运行:c:Windows/System32/cmd
  2. cd C:\Program Files\MySQL\MySQL Server 5.7\bin
  3. bin>.\mysql.exe -hlocalhost -uroot -p201408181
  •  net start MYSQL启动 
  •  List item
  •  net stop MYSQL关闭
  •  mysql -uroot -p201408181登录
  •  mysql -uroot -p隐藏密码登录
  • exit退出登录

3.数据库的查看与创建

  •  show databases;                         查看数据库
  •  MYSQL自带的数据库有四个
  •  use 名字;                                    使用数据库
  •  create database 名字;                创建数据库
  •  show tables                                查看是否有表

4.增删改查

 1.DQL:数据查询语言(凡是带有select关键字的都是查询语句)

  •  select         查

 2.DML:数据操作语言(凡是对表当中的数据进行增删改的都是DML)

  • insert          增
  • delete         删
  • update        改
  • 这个主要是操作表中的数据data.

 3.DDL:数据定义语言

  • 凡是带有create、drop、 alter的都是DDL。
  • DDL主要操作的是表的结构。不是表中的数据。
  • create: 新建,等同于增
  • drop:删除
  • alter:修改
  • 这个增删改和DML不同,这个主要是对表结构进行操作。

4. TCL:是事务控制语言

  • 事务提交:commit ;
  • 事务回滚: rollback;

4. DCL:数据控制语言

  • 例如:授权grant、 撤销权限revoke....

5.将sql的文件导入/导出

老杜p11导入表的链接:https://pan.baidu.com/s/13olV5qKdwzQRzoocl_Utgg 
                                      提取码:JIUQ
 导入方式:source 文件地址(source D:\course\03-MySQL\document\bjpowernode.sql)

导出方式:mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p201408181p; (要先退出登录)
 注意:路径中不要有中文!!!!

 6.查询数据库的表

  • dept是部门表
  • emp是员工表
  • salgrade 是工资等级表

1.怎么查看表中的数据呢?

  • select * from 表名; 统一执行这个SQL语句
  • select * from emp;     从emp表询
  • 有数据

2.不看表中的数据,只看表的结构,有一个命令:desc 表名;
3.select version();查看mysql的版本号
4.select database查看使用的那个数据库
5.mysql不见";"不执行";"表示结束
7.\c终止一条命令的输入
8.mysql不区分大小写
9.select 字段名 from 表名 简单查询,查询两个字段或着多个字段用“,”隔开,如果查询所有字段可以都写上,也可以使用*
10.给查询的列起别名,只是将查询的结果列名显示为你所修改的,原列明不变.

  • select  原名字 as 新名字 from 表名。
  • as可以省略,如果新别名里有空格用单引号括住新别名,双引号在oracle数据库中用不了,但在mysql可以用,所用在数据库尽量用单引号,别名有中文用单引号括起来,列参可以直接用数学符号运算

7.条件查询

条件查询不是将表中所有数据都查出来,而是查询出符合条件的。
 语法格式
 select 字段,字段2,字段3...
 from 表名
 where 条件

= 等于

where sal = 800;
where ename = 'smith' ;

 <>或!=不等于     >大于 >=大于等于   <小于<= 小于等于

 between ... and ...两个值之间,等同于>= and <=

where sal between 800 and 5000
  • 要遵循左小右大

 is null 为 null (is not null 不为空)

where comm is null;
where comm is not null

  •  在数据库中null不能用等号进行衡量,需要使用is null,因为数据库的null代表什么也没有,他不是一个值

 and 并且

where sal >= 800 and sal <= 5000

or或者
 

where sal = 800 or sal = 5000
where sal > 800 and (deptno = 20 or deptno = 30)

  •  and和or同时出现and的优先级大于or,如果想让or限制性就加小括号,在以后应用中如果不确定优先级就加小括号

 in包含,相当于多个or(not in不在这个范围内)

where sal in(800, 3000);
where ename in('smith', 'allen');
where sal not in(800,3000);

not 可以取非,主要用在is或者in中
like like称为模糊查询,支持%或下划线匹配

  • %匹配任意字符
  • 下划线,一个下划线只匹配一个字符
  • 找出名字以t结尾:where like '%t';
  • 找出名字以t开头:where like 't%';
  • 找出名字包含t:where like '%t%';
  • 找出名字第二个字母为a的:where like '_a%'
  • 找出名字有下划线的:使用“\”让下划线转译为普通: where like '%\_%'

8.排序

1.对查询的数据进行排序:select 显示的字段名 
                                        from 表名
                                        order by 排序的字段名;
                                   例如:            

SELECT ename,sal
FROM emp
ORDER BY sal;

   2.默认的排序是升序排序,如果想指定降序:select 显示的字段名 
                                                                         from 表名
                                                                         order by 排序的字段名 desc;
                                            指定升序:           select 显示的字段名 
                                                                         from 表名
                                                                         order by 排序的字段名 asc;                              
3.如果给多个字段进行排序:select 显示的字段名 
                                           from 表名
                                           order by 排序的字段名1,排序的字段名2;
 (先进行字段1的排序,只有字段1的排序遇到相等的时才会进行字段2的排序)
 
 查询工资在1250到3000的人进行倒叙排序:     

select ename,sal
from emp
where sal between 1250 and 3000
order by sal desc;
  •  先进行条件查询在排序

以上语句的执行顺序:

第一步:from

第二步:where

第三步:select

第四步:order(排序总是在最后执行)


9.单行函数

数据处理函数被称为单行函数,特点是一个输入对应一个输出

常见的单行处理函数有?

1.lower转换小写    在这里插入代码片

2.upper转换大写

3.substr取子串(substr(被截取的子串,起始下标,截取长度))

 获取名字首字母为A的员工名字?

SELECT ename
FROM emp
WHERE SUBSTR(ename, 1, 1) = 'A';

 4.length取长度  select length(ename) from emp;

5.concat函数进行字符串拼接 select concat(ename,empon) from emp;6.trim 去空格 
   

SELECT *
FROM emp
WHERE ename = TRIM('    KING');

7.str_to_date 将字串转化为日期

8.date_format 设置千分位

9.round生成随机数  

select round(rand()*10,0) from emp;
  •  “,”后是多少就是几位小数       
  • 保留全部小数                         
SELECT ROUND(1234.567) AS result FROM emp;
  •  保留一位小数     
select round(1234.567,1) as result from emp
  • 保留二位小数                        
 select round(1234.567,2) as result from emp
  • 保留十位                    
  select round(1234.567,-1) as result from emp

10.ifnull可以将null转化为具体值

 注意:只要null参与运算,最总结果一定是null,为了避免这个现象,需要ifnull函数
          ifnull函数用法:ifnull(数据,被当作哪个值)
      

select ename ,(sal + ifnull(comm,0)) * 12 as yearsal from emp;


  11.case...when..then...when...then...else...end

当员工的工作岗位是MANAGER的时候,发工资上调10%,当工作岗位是SALESMAN的时候,工资上调50%,其他正常(只修改查询结果不修改数据库) 

select ename ,job,(case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal end) as newsal 
from emp;

 select 后面可以跟某个表的字段名(可以等同看作变量名),也可以跟字面量/字面值(数据)       

select 21000 as num from dept;
select round(1234.567,0) as result from emp;

10.分组函数(又叫多行处理函数)

  1. 特点:输入多行最终输出一行
  2. 注意:分组函数在使用的时候必须先进行分组后才能使用,如果没有进行分组则会默认为一组
  • count 计数 
  • sum 求和
  • avg 平均值
  • max 最大值 select max(sal) from emp;
  • min 最小值

分组函数在使用时注意哪些?

  1. 分组函数主动忽略null,你不需要提前对null进行处理
  2. count(具体字段):表示统计该字段下所有不为null的元素总数
  3. count(*):统计当中的总行数(只要有一行数据count则++)    
  4. 分组函数不能直接使用在where子句中
  5. 所有的分组函数可以组合起来用   

11.分组查询

  •  定义:在实际应用中可能会让我们先进行分组,然后对每一组的数据进行操作,这个时候我们需要使用分组查询。

      select ...
      from ...
      group by ...

  •  将之前的关键字组合起来用的顺序?

       select ...
       from ...
       where ...
       group by ...
       order by ...

  • 以上关键字的顺序:

       1.from
       2.where
       3.group by
       4.select 
       5.order by

  • 在select语句中,如果有group by语句的话,select后面只能跟参加分组的字段,以及分组函数,其他一律不行。
  • 使用having可以对分完组之后的数据进一步过滤。having不能单独使用,having不能代替where,having必须和group by联合使用。
select deptno,max(sal)
from emp
group by deptno
having max(sal) > 3000;


 12.distinct(去重)

 distinct 只能出现在在有字段的最前方,目的是去重,当出现在两个字  段前面时表示两个字段联合去重。

SELECT DISTINCT job,deptno 
FROM emp;

13.链接

1.内连接

  • 定义:A和B连接,A和B之间没有主次关系
  • 特点:完成能够匹配上这个条件的数据查询出来

 笛卡尔现象

  •  当两张表进行连接没有任何条件限制时,最终查询结果的条数是两张表的乘积称为笛卡尔现象
  •  格式:select  项目名1,项目名2 from 表名1,表名2;
  •  怎么避免笛卡尔现象:使用时加条件

    1.sql92语法:

select ename,danme
from emp,dept
where emp.deptno = dept.deptno;

 最终查询的结果条数是14条,但是匹配次数没有减少,还是匹配了56次只不过进行了4选1

 这样写  就会减少匹配次数
       

select emp.ename,dept.danme
from emp,dept
where emp.deptno = dept.deptno;

 为了提高效率我们可以给表起别名

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

当然匹配次数越多效率越低,我们应尽量减少匹配次数
2. sql99语法:

select e.ename,d.dname
from emp e 
join dept d
on e.deptno = d.deptno;
  •   sql92缺点:结构不清晰,表的连接条件和后期帅选条件都放在了where
  •  sql99优点:表的链接是独立的,连接之后如果还需要进一步筛选还可以 再加where

 2.等值连接

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

3.非等值连接

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

4.自链接

自链接就是把一个数据库表当作两个来看,自己连接自己

5.外连接

1.左外连接:

select e.name,d.name
from dept d 
left join emp e
on e.deptno = d.deptno;

2.右外连接 

select e.name,d.name
from emp e 
right join dept d
on e.deptno = d.deptno;
  • right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表。
  • 在外连接当中,两张表连接,产生了主次关系。
  • 带有right的是右外连接,又叫做右连接,带有left的是左外连接,又叫做左连接,任何一个右连接都有左连接的写法,任何一个左连接都有右连接的写法

6.多表连接

语法:
select ...
from a
join b
on a和b的连接条件
join c
on a和c的连接条件
join d
on a和d的连接条件
案例:找出每个员工的部门名称以及工资等级,上级领导,要求显示员工名,领导名,部门名,薪资,薪资等级       

SELECT e.ename,e.sal,d.dname,s.grade,l.ename
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
LEFT JOIN emp l
ON e.mgr = l.empno;

14.子查询

1.where子句中的子查询
找出比最低工资高的人员的姓名和工资?

sql
SELECT ename,sal FROM emp WHERE sal > (SELECT MIN(sal) FROM emp)

2.from语句上查询
找出每个岗位的平均工资的薪资等级?

SELECT t.*,s.grade
FROM (SELECT job,AVG(sal) AS avgsal FROM emp GROUP BY job) t
JOIN salgrade s
ON t.avgsal BETWEEN s.losal AND s.hisal;

注意:表上的名字不要带关键字否则在查询表上的名字会查询关键字的作用而不会查询数据导致报错,起别名可以解决。
3.select后的子查询(了解,用其他方法更好)
找出每个员工的部门名,要求显示员工名、部门名?

sql
SELECT e.ename,(SELECT d.dname FROM dept d WHERE d.deptno = e.deptno) AS dname 
FROM emp e;

15.union(合并查询结果集)

案例:查询工作岗位是MANAGER和SALESMAN的员工? 

常规方式:

SELECT ename
FROM emp
WHERE job IN('MANGER','SALESMAN');

使用union:

SELECT ename FROM emp WHERE job = 'manager'
UNION
SELECT ename FROM emp WHERE job = 'SALESMAN';

union的效率会高一些,对于表连接来说每链接一次新表匹配的次数满足笛卡尔积会成倍的翻,但是union可以减少匹配次数

  • 如果a链接b链接c每张表10条记录那么匹配就是1000次,使用union就是100次+100次+100次

使用union的注意事项: 

  • union在进行结果集合并时,要求两个结果集的列数相同 
SELECT ename,job FROM emp WHERE job = 'SALESMAN'
UNION
SELECT ename,sal FROM emp WHERE job = 'MANAGER';
  • 结果集合并时列和列的数据类型也要保持一直(MYSQL可以,但语法严格的ORACLE不行)
SELECT ename,job FROM emp WHERE job = 'SALESMAN'
UNION
SELECT ename,sal FROM emp WHERE job = 'MANAGER';

16.limit

limit是将查询结果集的一部分取出来,通常在分页查询上使用

案例:按照薪资降序,取出排名在前五名的员工?

SELECT ename
FROM emp
ORDER BY sal DESC
LIMIT 0,10;
  • limit后第一个数是起始下标,“,”后是一页有几个数据 

注意:MYSQL上limit是在order by后执行的

案例:取出工资在3~5名的员工?

SELECT ename
FROM emp
ORDER BY sal DESC
LIMIT 2,3;

 如果我们每页几个数据而查询哪一页怎么写呢?

  • 每页显示pageSize条记录
  • 第pageNo页显示的数据就是:limit (pageNo-1)*pageSize ,pageSize

例如:

  • 第一页:limit 0,3  [0,1,2] 
  • 第二页:limit 3,3  [3,4,5] 
  • 第三页:limit 6,3  [6,7,8] 
  • 第四页:limit 9,3  [9,10,11] 

总结:

select ...

from...

where...

group by ...

having...

order by...

limit... 

执行顺序:

  1. from
  2. where 
  3. group by
  4. having
  5. select
  6. order by
  7. limit

17.34道练习题

1. 查询各个部门薪资最高的人

SELECT e.ename,t.*
FROM emp e
JOIN (SELECT deptno,MAX(sal) AS maxsal FROM emp GROUP BY deptno) t
ON t.deptno = e.deptno AND t.maxsal = e.sal

 2. 哪些人的薪资在部门平均水平之上

SELECT ename,sal,t.*
FROM emp e
JOIN (SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno) t
ON e.sal > t.avgsal AND e.deptno = t.deptno;

3. 取得部门中(所有人的)平均的薪水等级(老师题意应该有问题下面题是老师问题答案)

SELECT s.grade,t.*
FROM salgrade s
JOIN (SELECT AVG(sal) AS avgsal FROM emp GROUP BY deptno) t
ON t.avgsal BETWEEN s.losal AND s.hisal;

  取得部门所有人薪水等级的平均值

SELECT e.deptno,AVG(s.grade)
FROM emp e
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
GROUP BY e.deptno;

4. 不准用组函数(max),取得最高薪水

  • 倒叙排列
SELECT ename,sal
FROM emp
ORDER BY sal DESC
limit 1;
  • 表的自链接 
SELECT sal 
FROM emp
WHERE sal NOT IN (SELECT DISTINCT a.sal FROM emp a JOIN emp b ON a.sal < b.sal);

5. 取得平均薪水最高部门的部门编号(给出两种方案)

  • 倒序排列
SELECT deptno,AVG(sal) AS avgsal
FROM emp
GROUP BY deptno
ORDER BY avgsal DESC
LIMIT 1;
  • MAX 
SELECT deptno,AVG(sal) AS avgsal
FROM emp
GROUP BY deptno
HAVING avgsal = (SELECT MAX(t.avgsal) AS maxsal FROM emp e,(SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno) t);

6. 取得平均薪水最高部门的部门名称

SELECT t.avgsal,d.dname
FROM dept d
JOIN (SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno ORDER BY avgsal DESC LIMIT 1) t
ON t.deptno = d.deptno;

7.求部门平均薪水等级最低的部门名称

SELECT d.dname,t.*
FROM dept d
JOIN (SELECT b.mingrade,a.deptno FROM (SELECT MIN(t.sgrade) AS mingrade FROM (SELECT s.grade AS sgrade,t.* FROM salgrade s JOIN(SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno) t ON t.avgsal BETWEEN s.losal AND s.hisal) t) b JOIN (SELECT s.grade AS sgrade,t.* FROM salgrade s JOIN(SELECT deptno,AVG(sal) AS avgsal FROM emp GROUP BY deptno) t ON t.avgsal BETWEEN s.losal AND s.hisal) a WHERE b.mingrade = a.sgrade) t
ON d.deptno = t.deptno;

8. 取得比普通员工(员工代码没有在mgr字段上出现的)的最高薪水还要高的领导人姓名

SELECT e.sal,e.ename
FROM emp e
JOIN (SELECT MAX(sal) maxsal FROM emp WHERE empno NOT IN(SELECT DISTINCT mgr FROM emp WHERE mgr IS NOT NULL)) t
WHERE e.sal > t.maxsal;

9. 取得薪水最高的前五名

SELECT sal
FROM emp
ORDER BY sal DESC
LIMIT 5;

10.取得薪水最高的第六到第十名

SELECT sal
FROM emp
ORDER BY sal DESC
LIMIT 5,5;

11.取得最后入职的五名员工

SELECT ename,hiredate
FROM emp
ORDER BY hiredate DESC
LIMIT 5;

12.取得每个薪资等级有多少个员工

SELECT s.grade,COUNT(*)
FROM emp e
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
GROUP BY s.grade;

13.面试题

有三个表s(学生表),c(课程表),sc(学生选课表)

s(sno,sname)代表(学号和姓名)

c(cno,cname,cteacher) 代表(课号,课名,教师)

sc(sno,cno,scgrade)代表(学号,课号,成绩)

问题:

1.找出没选过''黎明''老师的所有学生姓名

SELECT * 
FROM s 
WHERE sname NOT IN(SELECT a.sname FROM s a JOIN (SELECT sno FROM sc WHERE cno = (SELECT cno FROM c WHERE cteacher = '黎明')) t ON a.sno = t.sno);

2.列出两门以上(含两门)不及格的学生姓名及成绩

SELECT s.sname,t.cgrade
FROM s s
JOIN (SELECT a.sno,b.countsno,a.cgrade FROM sc a JOIN (SELECT sno,COUNT(sno) AS countsno FROM sc WHERE cgrade < 60 GROUP BY sno) b ON b.countsno = 2 AND a.sno = b.sno) t
ON s.sno = t.sno;

3.即学过1号课程又学过2号课程的所有学生的姓名

SELECT s.sname,s.sno
FROM s s
JOIN (SELECT a.sno FROM (SELECT sno FROM sc WHERE cno = 1) a JOIN (SELECT sno FROM sc WHERE cno = 2) b ON a.sno = b.sno) t
WHERE s.sno = t.sno;

14.列出所有员工及领导名字

SELECT a.ename,b.ename
FROM emp a
LEFT JOIN emp b
ON a.mgr = b.empno;

15.列出受雇日期早于其直接领导员工的编号,姓名,部门名称

SELECT a.ename,a.deptno,a.empno
FROM emp a
JOIN emp b
ON a.mgr = b.empno AND a.hiredate < b.hiredate;

16.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门

SELECT d.dname,e.*
FROM emp e
RIGHT JOIN dept d
ON d.deptno = e.deptno;

17.列出有五个员工的所有部门

SELECT deptno
FROM emp e
GROUP BY e.deptno
HAVING COUNT(*)> 4;

18.列出薪金比SMITH多的所有员工信息

SELECT *
FROM emp 
WHERE sal > (SELECT sal FROM emp WHERE ename = 'SMITH');

19.列出所有"CLERK" (办事员)的姓名及其部门名称,部门的人数

SELECT a.ename,a.dname,b.*
FROM (SELECT e.ename,d.dname,e.deptno FROM emp e JOIN dept d ON e.deptno = d.deptno AND e.job = 'clerk') a
JOIN (SELECT deptno,COUNT(*) FROM emp GROUP BY deptno) b
ON a.deptno = b.deptno;

20.列出最低薪资大于1500的各个工作及从事此工作的全部雇佣人数(注意审题)

SELECT COUNT(*),job FROM emp GROUP BY job HAVING MIN(sal) > 1500;

 21.列出在部门''SALES"<销售部>工作的员工的姓名,假定不知道销售部的部门编号

SELECT e.ename
FROM emp e
JOIN (SELECT deptno FROM dept WHERE dname = 'SALES') t
ON e.deptno = t.deptno;

22.列出薪资高于公司平均薪资的所有员工,所在部门,上级领导,雇员的薪资等级

SELECT ename,d.dname,s.grade
FROM (SELECT ename,deptno,sal FROM emp WHERE sal > (SELECT AVG(sal) FROM emp)) t
JOIN dept d
ON  t.deptno = d.deptno
JOIN salgrade s
ON t.sal BETWEEN s.losal AND s.hisal;

23.列出与''SCOTT"从事相同工作的所有员工及部门名称

SELECT e.ename,d.dname
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
WHERE job = (SELECT job FROM emp WHERE ename = 'scott') AND e.ename != 'scott';

24.列出薪金等于部门30中员工的薪金的其他员工的姓名和薪金

SELECT ename,sal
FROM emp
WHERE sal IN(SELECT sal FROM emp WHERE deptno = 30) AND deptno != 30;

 25.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名

SELECT e.ename,e.sal,d.dname
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30);

26.列出在每个部门工作的员工数量,平均薪资和平均服务期限

SELECT a.*,t.times
FROM (SELECT deptno,COUNT(*),AVG(sal) FROM emp GROUP BY deptno) a
JOIN (SELECT deptno,AVG(TIMESTAMPDIFF(YEAR,hiredate,NOW())) AS times FROM emp GROUP BY deptno) t
ON a.deptno = t.deptno;

在MySQL如何计算两个日期的差?

  • timestampdiff(间隔类型,前一个日期,后一个日期)

间隔类型:

  • SECOND 秒
  • MINUTE 分钟
  • HOUR 小时
  • DAY 天
  • WEEK 星期
  • MONTH 月
  • QUARTER 季度
  • YEAR 年

27.列出所有员工的姓名,部门名和工资

SELECT e.ename,d.dname,e.sal
FROM emp e
JOIN dept d
ON e.deptno = d.deptno;

28.列出所有部门的详细信息和人数

SELECT d.*,t.coun
FROM dept d
LEFT JOIN (SELECT deptno,COUNT(*) coun FROM emp GROUP BY deptno) t
ON d.deptno = t.deptno;

29.列出各种工作的最低工资及从事此工作的雇员姓名

SELECT e.ename,t.minsal
FROM emp e
JOIN (SELECT job,MIN(sal) minsal FROM emp GROUP BY job) t
ON e.job = t.job AND e.sal = t.minsal;

30.列出各个部门的MANAGER(领导)的最低薪资

SELECT deptno,MIN(sal)
FROM emp
WHERE job = 'MANAGER'
GROUP BY deptno;

31.列出所有员工的年工资,按年薪从低到高排列

SELECT ename,(sal+IFNULL(comm,0))*12 AS yearsal
FROM emp
ORDER BY yearsal;

32.求出员工领导的薪水超过3000的员工名称与领导

SELECT t.ename,e.ename
FROM emp e
JOIN (SELECT ename,mgr FROM emp WHERE mgr IS NOT NULL) t
ON e.empno = t.mgr AND e.sal > 3000;

33.求出部门名称中,带's'字符的部门员工的工资合计,部门人数

SELECT SUM(sal),COUNT(e.ename)
FROM emp e
RIGHT JOIN dept t
ON t.deptno = e.deptno AND t.dname LIKE '%s%'
GROUP BY e.deptno;

34.给任职日期超过30年的员工加薪10%

UPDATE emp
SET sal = sal*1.1
WHERE TIMESTAMPDIFF(YEAR,hiredate,NOW()) > 30;

18.表的创建

 1.建表的语法格式:(建表属于DDL语句,DDL包括:create drop alter)

create table 表名(

字段名1  数据类型,

字段名2  数据类型,

字段名3  数据类型,

字段名4  数据类型

);

  • 表名:建议以t_或者tbl_开始,可读性强
  • 字段名:见名知意
  • 字段名和表名都属于标识符

2.mysql的数据类型 

常见数据类型:

  • varchar(最长255)   可变长度字符串(可以根据实际数据长度动态分布空间,但是数度慢)
  • char(最长255)    定长字符串(不管实际数据长度定义多少就是多长,可能会导致空间浪费但                            是速度快)
  • int(最长11)           数字中的整数型,等同于Java上的int
  • bigint      数字中的长整型,等同于Java上的long
  • float        单精度浮点型
  • double    双精度浮点型
  • date        短日期只有年月日
  • datetime  长日期包含年月日时分秒
  • clob      字符大对象(最多可以存储4G的字符串超过255个字符都要采用CLOB,例如一篇文章)
  • blob   二进制大对象(专门用来储存图片,声音,视频等流媒体数据,插入数据需要使用IO流)  

 3.删除表 

drop table 表名; //当表不存在就会报错

drop table if exists 表名; 这张表存在就删除

4.插入数据insert (DML)

语法格式:insert into 表名(字段1,字段2,字段3)value (值1,值2,值3);

insert语句执行成功必然会多一条记录,没写默认值为null

同时插入多条记录也是可以的

语法格式:insert into 表名(字段1,字段2,字段3)value (值1,值2,值3), (值1,值2,值3);

数据库命名规范:所有标识符小写,单词和单词之间下划线进行链接

5.insert插入日期

1.数字格式化:format(数字,'格式')

2.str_to_date('字符串日期','日期格式'):  将字符串varchar类型转化为date类型,通常在insert上

mysql日期格式:

  • %Y 年
  • %m 月
  • %d 日
  • %h 时
  • %i 分
  • %s 秒
INSERT INTO t_student(birth) VALUES(STR_TO_DATE('01-09-2001','%d-%m-%Y'));

如果格式为(年-月-日)后面可以不写格式

INSERT INTO t_student(birth) VALUES('1990-09-01');

3.date_format(日期类型数据,'日期格式'):将date类型转化为具有一定格式的varchar字符串类型

通常使用查询日期时,将展示的日期为varchar类型

SELECT DATE_FORMAT(birth,'%Y/%m/%d') FROM t_student;

如果不改变格式查询日期:

SELECT birth FROM t_student;

 如果想输入当前时间直接 now()

6.update修改(DML) 

语法格式:update 表名 set 字段名1==值1,字段名2==值2,字段名3==值3 where 条件

注意:没有条件限制就会改变所有数据

7.删除数据:delete(DML)

语法格式:delectd from 表名 where 条件

注意:没有条件限制就会删除所有数据

删除数据空间不会释放,只是把数据变成空,支持回滚后悔数据可以回复但效率比较低

8.将查询的结果当做一张新表创建

语法格式:create table 表名 as 查询的结果 

9.将查询结果插入一张表

语法格式:insert into 表名 查询结果

10.快速删除表中的数据

语法格式:truncate table 表名(DDL)

删除效率比较高,表被一次截断,物理删除,但不支持回滚

删的是数据表结构仍然在

11.对表结构进行修改

什么是对表结构的修改?

  • 添加一个字段,修改一个字段,删除一个字段

 我们在实际开发中一般不会对表结构进行修改,一旦修改表结构对应的Java代码会进行大量修改成本很高,所以我们不需要掌握,如果真的需要直接用工具,我们在Java上不会修改表

19.约束(constraint)

1.约束的作用?

 在创建表时我们需要给表中的字段增加一些约束,来保证表数据的完整性,有效性

2.约束包括哪些?

 非空约束 not null

唯一性约束  unique

主键约束  primary key(简称pk)

外键约束  foreign key (简称fk)

检查约束   check(MYSQL不支持,Orace支持)

3.非空约束 not null

约束的字段不能为空

案例:

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(32) NOT NULL
);

INSERT INTO t_vip(id,NAME) VALUES(1,'black');
INSERT INTO t_vip(id,NAME) VALUES(1);

报错信息:Column count doesn't match value count at row 1 

没有表级约束

4.唯一性约束 unique

约束字段不能重复但是可以为null

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(32) NOT NULL,
email VARCHAR(255) UNIQUE
);

INSERT INTO t_vip(id,NAME,email) VALUES(1,'black','[email protected]');
INSERT INTO t_vip(id,NAME,email) VALUES(2,'blank','[email protected]');
INSERT INTO t_vip(id,NAME,email) VALUES(3,'black','[email protected]');

报错信息:Duplicate entry '[email protected]' for key 'email' 

5.如果多个字段联合唯一性应该怎么写?

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(32),
email VARCHAR(255),
UNIQUE(NAME,email)
);

INSERT INTO t_vip(id,NAME,email) VALUES(1,'black','[email protected]');
INSERT INTO t_vip(id,NAME,email) VALUES(2,'cool','[email protected]');
INSERT INTO t_vip(id,NAME,email) VALUES(3,'cool','cool@');
INSERT INTO t_vip(id,NAME,email) VALUES(4,'yellow','cool');
INSERT INTO t_vip(id,NAME,email) VALUES(5,'cool','cool');
INSERT INTO t_vip(id,NAME,email) VALUES(6,'pink','[email protected]');
INSERT INTO t_vip(id,NAME,email) VALUES(7,'[email protected]','pink');
INSERT INTO t_vip(id,NAME,email) VALUES(8,'green','green');
INSERT INTO t_vip(id,NAME,email) VALUES(9,'green','green');

错误信息:Duplicate entry 'green-green' for key 'NAME'

只有加入id为9时才出现错误,只有加入两组数据的name和email都相同时才报错

这个约束是表级别约束 

6.not null和unique联合使用

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(32) NOT NULL UNIQUE
);

DESC t_vip;

INSERT INTO t_vip(id,NAME) VALUES(1,'black');
INSERT INTO t_vip(id,NAME) VALUES(2,'black');
INSERT INTO t_vip(id,NAME) VALUES(3);

 在mysql中如果一个字段同时被not null和unique同时约束的话,该字段自动变成主键字段(Oracle不是这样)

7.主键约束 primary key 简称PK(重点)

什么是主键以及它的作用?

主键值是每一行记录的唯一标识

任何一张表都要有主键,没有主键表无效

一张表的主键约束只能添加一个

主键一般都是数字是定长的不建议varchar来做主键

主键的特征:not null+unique(主键值不能是空也不能重复)

DROP TABLE t_vip;
CREATE TABLE t_vip(
id INT PRIMARY KEY,
NAME VARCHAR(255)
);

INSERT INTO t_vip(id,NAME) VALUES(1,'zhangsan');
INSERT INTO t_vip(id,NAME) VALUES(2,'lisi');
INSERT INTO t_vip(id,NAME) VALUES(2,'baiye');

错误信息:Duplicate entry '2' for key 'PRIMARY'

也可以这样写表示表级约束,前面是列级约束

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(255),
PRIMARY KEY(id)
);

 表级约束主要给多个字段起来添加约束

id和name联合起来做主键是复合主键,但在实际开发中主键存在的意义就是这行记录的身份证号只要意义达到即可,单一主键可以做到复合主键比较复杂不建议使用

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(255),
PRIMARY KEY(id,NAME)
);

INSERT INTO t_vip(id,NAME) VALUES(1,'zhangsan');
INSERT INTO t_vip(id,NAME) VALUES(2,'lisi');
INSERT INTO t_vip(id,NAME) VALUES(2,'baiye');
INSERT INTO t_vip(id,NAME) VALUES(2 ,'baiye');

主键除了单一主键和复合主键还可以这样进行分类?

  • 自然主键:主键是一个自然数和业务没关系
  • 业务主键:主键值和业务紧密相关

在实际开发中自然主键使用较多,主键不重复就好不需要有意义,主键一但和业务挂钩那么业务变动可能会影响主键值 

在mysql中有一种机制可以帮助我们自动维护一个主键值

CREATE TABLE t_vip(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(255)
);

INSERT INTO t_vip(NAME) VALUES('zhangsan');
INSERT INTO t_vip(NAME) VALUES('lisi');
INSERT INTO t_vip(NAME) VALUES('baiye');
INSERT INTO t_vip(NAME) VALUES('baiye');

AUTO_INCREMENT表示自增,从1开始

8.外键约束 foreign key 简称 fk(重点)

当两张表有父子关系时,子表上与父表关联的字段为保证数据有效需要加外键约束,被引用的字段可以不是主键可以为null但是必须具有唯一性

CREATE TABLE t_class(
classno INT PRIMARY KEY,
classname VARCHAR(255)
);

CREATE TABLE t_student(
NO INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(255),
cno INT,
FOREIGN KEY(cno) REFERENCES t_class(classno)
);

INSERT INTO t_class(classno,classname) VALUES(1001,'商丘一高');
INSERT INTO t_class(classno,classname) VALUES(1002,'商丘二高');

INSERT INTO t_student(NAME,cno) VALUES('liuqi',1001);
INSERT INTO t_student(NAME,cno) VALUES('fangao',1001);
INSERT INTO t_student(NAME,cno) VALUES('feng',1002);
INSERT INTO t_student(NAME,cno) VALUES('bailan',1002);
INSERT INTO t_student(NAME,cno) VALUES('bailan',1003);

错误信息:Cannot add or update a child row: a foreign key constraint fails (`wasd`.`t_student`, CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `t_class` (`classno`))

20.存储引擎(了解)

1.什么是存储引擎

存储引擎是mysql数据库独有的术语,Oracle数据库有但不叫这个名字

存储引擎是一个表存储或组织数据的方式,不同的存储引擎表存储数据方式不同 

2.怎么给表添加/指定“存储引擎”?

ENGINE来指定存储引擎

CHARSET来指定这张表的字符编码方式

mysql默认的存储引擎是InnoDB

mysql默认的字符编方式是utf-8

CREATE TABLE t_vip(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(255)
))ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO t_vip(NAME) VALUES('白也');
INSERT INTO t_vip(NAME) VALUES('柳七');
INSERT INTO t_vip(NAME) VALUES('张三');
INSERT INTO t_vip(NAME) VALUES('心悦');
INSERT INTO t_vip(NAME) VALUES('琼落');
INSERT INTO t_vip(NAME) VALUES('十六');

3.查看mysql支持哪些存储引擎

show engines

mysql支持九大存储引擎,5.7.25支持八个,每个版本支持的不同

4.mysql常用的存储引擎

 1.InnoDB

默认的存储引擎,也是一个重量级存储引擎

最主要的特点支持事务保证数据安全,效率较低不能压缩不能转化为只读

主要特征:

  • 每个InnoDB表在数据库目录以.fm格式文件表示
  • InnoDB表空间tablespace被用于存储表的内容(表空间是逻辑名称,表空间存储数据+索引)
  • 提供一组用来记录事务性活动的日志文件
  • 同commit(提交),savepoing及ROLLBACK(回滚)支持事务处理
  • 提供全ACID兼容
  • 在MYSQL服务器崩溃后提供自动回复
  • 多版本(MVCC)和行级锁定
  • 支持外键及引用的完整性,包括级联删除和更新

2.MyISAM

     他管理的表具有以下特征:

            使用三个文件表示每个表:

                 格式文件:存储表结构的定义

                 数据文件:存储表行的内容

                 索引文件:存储表上的索引

         可以转换为压缩,只读表节省空间

对一张表来说只要是主键,或者加有unique约束的字段会自动创建索引

 3.MEMORY

使用memory存储引擎的表其数据存储在内存上,且行的长度固定不能包含text和blob字段,这两个特点使memory存储引擎非常快,但一关机数据消失

21.事务(重点)

1.什么是事务?

一个事务其实就是一个完整的业务逻辑

2.只有DML才有事务,其他语句和事务无关

  • insert
  • delete
  • update 

只有这三个增删改语句才有事务,只要涉及增删改数据安全就是第一位

3.一个事务本质上就是多条语句同时成功或者失败 

4.事务是怎么做到多条语句同时成功或者失败呢?

  • 开启事务:
  • 所需要的DML操作
  • 结束事务!

在事务执行过程中。每一条DML的操作都会记录到“事务性活日志文”中

在事务执行过程中我们可以提交事务也可以回滚事务

提交事务:清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中,标志着事物成功结束

回滚事务:清空事务性活动的日志文件,将所有的DML操作全部撤销,标志着事务失败结束

5.怎么提交事务,怎么回滚事务?

提交事务:commit

回滚事务:rollback

mysql默认情况下自动提交事务,那怎么自己提交事务呢?

START TRANSACTION;

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,'jjj','yyyy');
SELECT * FROM dept;
ROLLBACK;
SELECT * FROM dept;

事务一旦提交回滚就没有作用

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,'jjj','yyyy');
SELECT * FROM dept;
COMMIT;
ROLLBACK;
SELECT * FROM dept;

6.事务的特性

A.原子性

C.一致性

I.隔离性

D.持久性

7.事务与事务之间有4个隔离级别

  • 读未提交(read uncommited):事务A可以读取事务B未提交的数据(最低的隔离级别)

这种隔离级别可能会出现脏读现象(Dirty read)我们称之为读到了脏数据,一般这种隔离级别都是在理论上,大多数的数据库的隔离级别都是二档起步

  • 读已提交(read commited):事务A只能读取事务B已提交的数据

这种隔离级别解决了脏读现象,但是不可重复读取数据就是每次提交后读取的数据都不一样

Oracle数据库默认的隔离级别就是read committed

  • 可重复读(repeatable read):事务A开启后不管多久事务A读取的数据都是一致的,即使事务B把数据修改并且提交,事务A读取的数据不变

解决了不可重复读取的问题,但可能会出现幻影读每次读取的数据都是幻象,MySQL默认的隔离级别就是这个

  • 序列化/串行化(serializable):事务排队不能并发,可以解决所有问题 (最高隔离级别效率最低)

每次读取的数据都是最真实的,也是效率最低的

8.验证各种隔离级别

查看隔离级别:

SELECT @@tx_isolation;

设置全局的隔离级别:

  • 命令行窗口:
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
    
  • sqlyog:
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    

22.索引 

1.什么是索引

在mysql上索引是B-Tree数据结构,遵循左小右大的原则,采用中序遍历的方式进行遍历取数据  

 mysql查询方面主要有两种方式:

  1. 全表扫面
  2. 根据索引检索

索引是所有数据库优化的重要手段,优化时优先考虑索引  

2.索引的实现原理

  1. 在任何数据库当中主键上都会自动添加索引对象 。id字段上自动有索引,因为id是PK,另外在mysql上一个字段如果有unique约束的话,也会自动创建索引。
  2. 在任何数据库中,任何一张表的任何一条记录在硬盘存储上都有一个硬盘的物理存储编号
  3. 在mysql上索引是一个单独对象,不同的存储引擎以不同的形式存在,在MyISAM存储引擎中索引存储在一个.MYI文件中,在InnoDB存储引擎中索引存储在一个逻辑名称叫做tablespace当中,在MEMORY存储引擎当中引擎被存储在内存当中。不管索引存储在哪里。索引在mysql上都是以树(自平衡二叉树:B-Tree)的形式存在

3.什么时候使用索引 

  1. 数据量庞大(具体值需要测试,每硬盘不同)
  2. 字段经常出现在where后面,以条件的形式存在
  3. 改字段很少DML(增删改)操作 ,因为DML后索引需要重新排序

不要随意添加索引 ,因为索引也是需要维护的,太多会降低系统性能

建议通过unique约束的字段进行查询或主键查询使用索引效率比较高

4.索引的创建删除 

 创建索引:create index 索引的名字 on 添加索引的位置;

CREATE INDEX emp_ename_index ON emp(ename);

删除索引:drop index  索引的名字 on 表名;

DROP INDEX emp_ename_index ON emp;

5.查看sql语句是否使用索引

explain select * from 表名 where 列名 = 条件;

explain select * from emp where ename = 'king';

6.索引的失效

  • 在模糊查询使用%开始索引失效(在sqlyog不会失效)
EXPLAIN SELECT * FROM emp WHERE ename = '%T';
  • 使用or时要求两边条件都有索引时才会使用索引,否则失效
EXPLAIN SELECT * FROM emp WHERE ename = 'king' OR job = 'manager';
  • 使用复合索引(多个字段联合起来添加一个索引叫做复合索引)没有使用左侧的列查找索引失效
CREATE INDEX emp_ename_index ON emp(sal,job);

EXPLAIN SELECT * FROM emp WHERE job = 'manager';
索引失效

EXPLAIN SELECT * FROM emp WHERE sal = 800;
索引生效
  • where中索引参加了运算
EXPLAIN SELECT * FROM emp WHERE sal+100 = 900;
  • where上索引列使用了函数
EXPLAIN SELECT * FROM emp WHERE LOWER(ename) = 'smith';

7.索引的分类

单一索引:一个字段添加索引

复合索引:多个字段联合添加索引

主键索引:主键上添加索引

唯一性索引:具有unique约束的字段上添加索引

注意:唯一性较弱的字段上添加索引意义不大,唯一性越强效率越高

23.视图

什么是视图?

view:站在不同的角度去看待同一份数据

创建视图:CREATE VIEW 命名 AS DQL语句;

CREATE VIEW dept2_view AS SELECT * FROM dept2;

删除视图:DROP VIEW 名字;

DROP VIEW dept2_view;

用视图做什么?·

我们可以面向视图对象进行增删改查,对视图对象的增删改查会导致原表被操作

CREATE TABLE dept2 AS SELECT * FROM dept;
CREATE TABLE emp2 AS SELECT * FROM emp;
SELECT * FROM emp2;

CREATE VIEW dept2_emp2_view AS SELECT e.ename,e.sal,d.dname FROM emp2 e JOIN dept2 d ON d.deptno = e.deptno;
DROP VIEW dept2_emp2_view;
SELECT * FROM dept2_emp2_view;
UPDATE dept2_emp2_view SET sal = 1000 WHERE ename = 'smith';

emp2上smith的工资也被修改为1000了  

24.数据库设计三范式(面试重点)

第一范式:要求任何一张表必须有主键每一个字段,原子性不可再分

第二范式:建立在第一范式基础之上,要求非主键字段必须完全依赖主键,不要产生部分依赖。

第三范式:建立在第二范式基础之上,要求非主键字段直接依赖主键,不要产生传递依赖

设计数据库的时按照以上范式进行可以避免表中数据冗余造成空间的浪费,但是这是理论上的,我们在实际开发中可能会拿冗余换速度,因为表与表之间连接越多效率越低

你可能感兴趣的:(笔记,mysql,数据库,database)