MySql数据库总结以及对事务的特性等理解,包括34道经典面试题,欢迎指正呀

文章目录

一、基本概念

1什么是数据库?什么是数据库管理系统?什么是sql?
数据库:
	DataBase,简称DB.按照一定格式存储数据的一些文件的组合
	存储数据的仓库,实际上就是一堆文件.这些文件中存储了具有特定格式的数据 
数据库管理系统:
	DataBaseManagement,简称DBMS
	数据库管理系统是专门进行管理数据库的,数据库管理系统可以对数据库当中的数据进行增删改查
	MySql Oracle MS SqlServer
	sql:结构化查询语言
	sql是一套标准
	三者之间的关系
		DBMS--> 通过执行sql语句--> DB	
2.安装mysql
1.安装mysql
2.需要进行mysql数据库实例配置
3.端口号:port是任何一个软件或应用都会有的,端口号是应用的唯一代表,具有唯一性
mysql数据库启动的时候这个服务默认端口是3306.
4.字符编码方式?
	设置mysql数据库的字符集编码方式为utf8
	一定要注意:先选中第三个按钮,然后在选择utf8字符集
5.选择环境变量怕配置path	
6.mysql数据库超级管理员的用户名不能改,是root
	你需要设置密码,一般为123456或者root
	也可以激活root账户远程访问,
		激活后可以在外地登录
3.mysql数据库的卸载
1.双击安装包卸载删除
2.删除目录:
	2.1.把c:\programData下面的MySql目录删除
	2.2.把c:\ProgramFiles(x86)下面的MySql目录删除
	卸载结束
4.查看计算机上的服务
计算机->右键管理->服务与应用程序->服务->找mysql服务
mysql默认启动状态,只有启动了mysql才能用
也可右键mysql进行属性的设置,改变其手动还是自动等
5.windows操作系统使用命令启停mysql
net stop MySql 停mysql服务
net start MySql 启动服务器
6.登录MySql
命令终端:
	mysql -uroot -proot
exit 退出mysql
7.mysql的常用命令
1.退出 exit
2.登录 mysql -uroot -proot
3.查看有全部数据库  show databases;
	注意: 以分号结尾
4.怎么使用某个数据库?
	use 数据库名字
	就进入了这个数据库
5.创建数据库
	craete database 数据库名字
6.show tables 查看数据库当中有哪些表
7.查看mysql的版本
	select version();
8.查看当前使用的是哪个数据库? 
	select database();
mysql语句是不见分号不执行,分号表示结束!
8.表的理解
数据库当中最基本的单位是表. table
什么是表?为什么用表来存储数据呢?
数据库当中是以表格的形式存储数据的,任何一张表都有行和列
姓名	性别	年龄(字段)
-----------------
张三	男	13   -->行:数据/记录
李四	男	48
张乾康	男	45
袁梦梦	男	86
行(row):被称为数据/记录
列(column):被称为字段
	每个字段都有字段名,数据类型,约束(唯一性)等属性
		字段名:是一个普通的名字
		数据类型:字符串,数字.日期
		约束:很多,例唯一性约束,不能重复
9.sql分类
sql分为
	DQL: 
		数据查询语言(凡是带有select)
		select...
	DML:
		数据操作语言(凡是对表当中的数据进行增删改查的都是DML)
		insert delete update
		主要操作数据
	DDL:
		数据定义语言
		凡是带有create(新增) drop(删除) alter(修改) 
		主要是操作表的结构 都是定义语言(DDL)
	TCL:
		是事务控制语言
		包括事物提交:commit
		事务回滚: rollback
	DCL:
		是数据控制语言
			例授权grant...
				撤销权限revoke...
10.导入表
1.进入数据库 use 数据库名
	use bjpowernode;
2.将表结构导入:source 路径(不要有中文)
 	source D:\mysql_source\bjpowernode.sql;
 	bjpowernode.sql文件:
 	
		DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;

CREATE TABLE DEPT
       (DEPTNO int(2) not null ,
	DNAME VARCHAR(14) ,
	LOC VARCHAR(13),
	primary key (DEPTNO)
	);
CREATE TABLE EMP
       (EMPNO int(4)  not null ,
	ENAME VARCHAR(10),
	JOB VARCHAR(9),
	MGR INT(4),
	HIREDATE DATE  DEFAULT NULL,
	SAL DOUBLE(7,2),
	COMM DOUBLE(7,2),
	primary key (EMPNO),
	DEPTNO INT(2) 
	)
	;

CREATE TABLE SALGRADE
      ( GRADE INT,
	LOSAL INT,
	HISAL INT );




INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
10, 'ACCOUNTING', 'NEW YORK'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
20, 'RESEARCH', 'DALLAS'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
30, 'SALES', 'CHICAGO'); 
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
40, 'OPERATIONS', 'BOSTON'); 
commit;
 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7369, 'SMITH', 'CLERK', 7902,  '1980-12-17'
, 800, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7499, 'ALLEN', 'SALESMAN', 7698,  '1981-02-20'
, 1600, 300, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7521, 'WARD', 'SALESMAN', 7698,  '1981-02-22'
, 1250, 500, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7566, 'JONES', 'MANAGER', 7839,  '1981-04-02'
, 2975, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7654, 'MARTIN', 'SALESMAN', 7698,  '1981-09-28'
, 1250, 1400, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7698, 'BLAKE', 'MANAGER', 7839,  '1981-05-01'
, 2850, NULL, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7782, 'CLARK', 'MANAGER', 7839,  '1981-06-09'
, 2450, NULL, 10); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7788, 'SCOTT', 'ANALYST', 7566,  '1987-04-19'
, 3000, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7839, 'KING', 'PRESIDENT', NULL,  '1981-11-17'
, 5000, NULL, 10); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7844, 'TURNER', 'SALESMAN', 7698,  '1981-09-08'
, 1500, 0, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7876, 'ADAMS', 'CLERK', 7788,  '1987-05-23'
, 1100, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7900, 'JAMES', 'CLERK', 7698,  '1981-12-03'
, 950, NULL, 30); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7902, 'FORD', 'ANALYST', 7566,  '1981-12-03'
, 3000, NULL, 20); 
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES ( 
7934, 'MILLER', 'CLERK', 7782,  '1982-01-23'
, 1300, NULL, 10); 
commit;
 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
1, 700, 1200); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
2, 1201, 1400); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
3, 1401, 2000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
4, 2001, 3000); 
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
5, 3001, 9999); 
commit; 		

3.导入后表的结构:
mysql> show tables;
+-----------------------+
| Tables_in_bjpowernode |
+-----------------------+
| dept 部门表            |
| emp  员工表            |
| salgrade  工资表       |
+-----------------------+

10.1后面要用到的这个bjpowernode数据库中的三张表:

1.emp员工表
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
2.部门表:
	mysql> select * from dept;
    +--------+------------+----------+
    | DEPTNO | DNAME      | LOC      |
    +--------+------------+----------+
    |     10 | ACCOUNTING | NEW YORK |
    |     20 | RESEARCH   | DALLAS   |
    |     30 | SALES      | CHICAGO  |
    |     40 | OPERATIONS | BOSTON   |
    +--------+------------+----------+
3.工资等级表:
	mysql> select * from salgrade;
    +-------+-------+-------+
    | GRADE | LOSAL | HISAL |
    +-------+-------+-------+
    |     1 |   700 |  1200 |
    |     2 |  1201 |  1400 |
    |     3 |  1401 |  2000 |
    |     4 |  2001 |  3000 |
    |     5 |  3001 |  9999 |
    +-------+-------+-------+
11.查看表中的数据
select * from 表名; //执行这个sql语句
mysql> select * from emp; //员工表
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+

mysql> select * from dept; 部门表
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

mysql> select * from salgrade; //工资表
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+
12.不看表中的数据,只看表中的结构=>desc
mysql> desc emp; //查看员工的结构  desc的缩写,describe,描述
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO    | int(4)      | NO   | PRI | NULL    |       |
| ENAME    | varchar(10) | YES  |     | NULL    |       |
| JOB      | varchar(9)  | YES  |     | NULL    |       |
| MGR      | int(4)      | YES  |     | NULL    |       |
| HIREDATE | date        | YES  |     | NULL    |       |
| SAL      | double(7,2) | YES  |     | NULL    |       |
| COMM     | double(7,2) | YES  |     | NULL    |       |
| DEPTNO   | int(2)      | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+

二、DQL语句

13.DQL简单查询语句
13.1.简单查询一个字段?
	select 字段名 from 表名
		select from 都是关键字
		字段名 表名是标识符
	强调:
		对于sql语句是通用的,
		所有的sql语句都是以";"结尾
		另外sql语句不区分大小写,都可以
13.2 查询DNAME这个字段
    mysql> select dname from dept;
    +------------+
    | dname      |
    +------------+
    | ACCOUNTING |
    | RESEARCH   |
    | SALES      |
    | OPERATIONS |
    +------------+
13.3查询多个字段怎么办?
	查询的多字段用逗号隔开
	mysql> select dname,loc from dept;
    +------------+----------+
    | dname      | loc      |
    +------------+----------+
    | ACCOUNTING | NEW YORK |
    | RESEARCH   | DALLAS   |
    | SALES      | CHICAGO  |
    | OPERATIONS | BOSTON   |
    +------------+----------+
13.4查询所有字段,可以使用*,也可以把字段都写上
	select * from dept
13.5给查询的列起别名
	mysql> select deptno,dname as deptName from dept;
    +--------+------------+
    | deptno | deptName   |
    +--------+------------+
    |     10 | ACCOUNTING |
    |     20 | RESEARCH   |
    |     30 | SALES      |
    |     40 | OPERATIONS |
    +--------+------------+
    注意:select语句是不会修改原表的
    as 关键字也可以省略, 使用空格 
    mysql> select deptno,dname deptName from dept;
   13.5.1 若你起的别名存在空格怎么办? 例:你起的为 dept Name
    	可以加引号(''或"")将其包裹住
    		 mysql> select dname 'dept Name' from dept;
    		+------------+
            | dept Name  |
            +------------+
            | ACCOUNTING |
            | RESEARCH   |
            | SALES      |
            | OPERATIONS |
            +------------+
        注意:在所有的数据库中,字符串统一使用单引号括起来
        单引号是标准,双引号在oracle中不能使用
14.计算每个员工的年薪
年薪:sal*12
    mysql> select ename,sal*12 as salYear from emp; //字段可以使用数学表达式
    +--------+----------+
    | ename  | salYear  |
    +--------+----------+
    | SMITH  |  9600.00 |
    | ALLEN  | 19200.00 |
    | WARD   | 15000.00 |
    | JONES  | 35700.00 |
    | MARTIN | 15000.00 |
    | BLAKE  | 34200.00 |
    | CLARK  | 29400.00 |
    | SCOTT  | 36000.00 |
    | KING   | 60000.00 |
    | TURNER | 18000.00 |
    | ADAMS  | 13200.00 |
    | JAMES  | 11400.00 |
    | FORD   | 36000.00 |
    | MILLER | 15600.00 |
    +--------+----------+
15.条件查询
不是将所有的数据都查询出来,是查询出来符合条件的
语法格式:	
	select 
		字段一,字段二,...
	from
		表名
	where
		条件...
1.查询工资等于(=)800的员工姓名和编号
    mysql> select empno,ename from emp where sal=800;
    +-------+-------+
    | empno | ename |
    +-------+-------+
    |  7369 | SMITH |
    +-------+-------+
2.查询工资不等于(<>或!=)800的员工姓名和编号和薪资
    mysql> select empno,ename,sal from emp where sal<>800;
    +-------+--------+---------+
    | empno | ename  | sal     |
    +-------+--------+---------+
    |  7499 | ALLEN  | 1600.00 |
    |  7521 | WARD   | 1250.00 |
    |  7566 | JONES  | 2975.00 |
    |  7654 | MARTIN | 1250.00 |
    |  7698 | BLAKE  | 2850.00 |
    |  7782 | CLARK  | 2450.00 |
    |  7788 | SCOTT  | 3000.00 |
    |  7839 | KING   | 5000.00 |
    |  7844 | TURNER | 1500.00 |
    |  7876 | ADAMS  | 1100.00 |
    |  7900 | JAMES  |  950.00 |
    |  7902 | FORD   | 3000.00 |
    |  7934 | MILLER | 1300.00 |
    +-------+--------+---------+
3.查询薪资小于(<)2000的员工姓名和薪资
    mysql> select ename,sal from emp where sal<2000;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | ALLEN  | 1600.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    | TURNER | 1500.00 |
    | ADAMS  | 1100.00 |
    | JAMES  |  950.00 |
    | MILLER | 1300.00 |
4.查询SMITH得薪资和编号
    mysql> select empno,sal from emp where ename='SMITH';
    +-------+--------+
    | empno | sal    |
    +-------+--------+
    |  7369 | 800.00 |
    +-------+--------+
5.查询薪资在2450到3000的员工的信息?闭区间between..and...或 >=...and <=...
    	select ename,sal from emp where sal between 2450 and 3000;
    也可用
    	select ename,sal from emp where sal >= 2450 and sal <= 3000;
    +-------+---------+
    | ename | sal     |
    +-------+---------+
    | JONES | 2975.00 |
    | BLAKE | 2850.00 |
    | CLARK | 2450.00 |
    | SCOTT | 3000.00 |
    | FORD  | 3000.00 |
    +-------+---------+	
    注意:使用between and时必须遵顼左小右大的方式
6.查询哪些员工的津贴为null?
    mysql> select ename,sal from emp where comm is null; //用is来表示等于,不能用=号来表示,因为数据库中的null表示什么也没有,不能用=来划等号
 +--------+---------+------+
| ename  | sal     | comm |
+--------+---------+------+
| SMITH  |  800.00 | NULL |
| JONES  | 2975.00 | NULL |
| BLAKE  | 2850.00 | NULL |
| CLARK  | 2450.00 | NULL |
| SCOTT  | 3000.00 | NULL |
| KING   | 5000.00 | NULL |
| ADAMS  | 1100.00 | NULL |
| JAMES  |  950.00 | NULL |
| FORD   | 3000.00 | NULL |
| MILLER | 1300.00 | NULL |
+--------+---------+------+
7.查询哪些员工的津贴不为null?(is not)
    mysql> select ename,sal,comm from emp where comm is not null;
    +--------+---------+---------+
    | ename  | sal     | comm    |
    +--------+---------+---------+
    | ALLEN  | 1600.00 |  300.00 |
    | WARD   | 1250.00 |  500.00 |
    | MARTIN | 1250.00 | 1400.00 |
    | TURNER | 1500.00 |    0.00 |
    +--------+---------+---------+
8.找出工作岗位是manager,并且工资大于2500的员工信息?
	mysql> select ename,sal,job from emp where job='manager' and sal>2500;
    +-------+---------+---------+
    | ename | sal     | job     |
    +-------+---------+---------+
    | JONES | 2975.00 | MANAGER |
    | BLAKE | 2850.00 | MANAGER |
    +-------+---------+---------+
9.查询工作岗位是manager和salesman的员工信息?
    mysql> select ename,job from emp where job='manager' or job='salesman';
    +--------+----------+
    | ename  | job      |
    +--------+----------+
    | ALLEN  | SALESMAN |
    | WARD   | SALESMAN |
    | JONES  | MANAGER  |
    | MARTIN | SALESMAN |
    | BLAKE  | MANAGER  |
    | CLARK  | MANAGER  |
    | TURNER | SALESMAN |
    +--------+----------+
10.查询工资大于2500并且部门编号为10或者为20的员工信息?
	mysql> select ename,sal,deptno from emp where sal>2500 and (deptno=10 or deptno=20); //加括号提升优先级
    +-------+---------+--------+
    | ename | sal     | deptno |
    +-------+---------+--------+
    | JONES | 2975.00 |     20 |
    | SCOTT | 3000.00 |     20 |
    | KING  | 5000.00 |     10 |
    | FORD  | 3000.00 |     20 |
    +-------+---------+--------+
    注意:and和or同时出现,and的优先级较高
11.查询工作岗位是manager和salesman的员工信息?(in)
    mysql> select ename,job from emp where job in ('manager','salesman');
    +--------+----------+
    | ename  | job      |
    +--------+----------+
    | ALLEN  | SALESMAN |
    | WARD   | SALESMAN |
    | JONES  | MANAGER  |
    | MARTIN | SALESMAN |
    | BLAKE  | MANAGER  |
    | CLARK  | MANAGER  |
    | TURNER | SALESMAN |
    +--------+----------+
    注意:in不是一个区间,in后面跟的是具体的值.
12.查询工作岗位不是manager和salesman的员工信息?(not in)
    mysql> select ename,job from emp where job not in ('manager','salesman');
    +--------+-----------+
    | ename  | job       |
    +--------+-----------+
    | SMITH  | CLERK     |
    | SCOTT  | ANALYST   |
    | KING   | PRESIDENT |
    | ADAMS  | CLERK     |
    | JAMES  | CLERK     |
    | FORD   | ANALYST   |
    | MILLER | CLERK     |
    +--------+-----------+
12.找出名字中含有o的?(like模糊下查询)
	% 百分号表示任意多个字符
	_ 下划线表示任意一个字符
       mysql> select ename from emp where ename like '%o%';
    +-------+
    | ename |
    +-------+
    | JONES |
    | SCOTT |
    | FORD  |
    +-------+
   12.2找出第二个字母是a的员工?
   mysql> select ename from emp where ename like '_a%';
    +--------+
    | ename  |
    +--------+
    | WARD   |
    | MARTIN |
    | JAMES  |
    +--------+
   12.3找出第三个字母是r的?
    mysql> select ename ename_R from emp where ename like '__r%';
    +---------+
    | ename_R |
    +---------+
    | WARD    |
    | MARTIN  |
    | TURNER  |
    | FORD    |
    +---------+
 12.4例如现在有个表t_student学生表的name字段
    有zhangsan,lisi,wangwu,jack_son,...
    找出名字中含有"_"的?
    	1.select name from t_student where name like '%_%'; //这样不行,因为下划线_ 具有特殊意义,这样就会把所有的全部找出来
    	2.select name from t_sudent where name like '%\_%'; //需要用\进行转义
16.查询所有员工工资
1.查询工资并升序排列
	mysql> select ename,sal from emp order by sal; //使用order by进行升序排列
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | WARD   | 1250.00 |
    | MARTIN | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | FORD   | 3000.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
2.查询工资并降序排列
mysql> select ename,sal from emp order by sal desc; //通过在最后加上desc进行降序排列
+--------+---------+
| ename  | sal     |
+--------+---------+
| KING   | 5000.00 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| JONES  | 2975.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| ALLEN  | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
| WARD   | 1250.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SMITH  |  800.00 |
+--------+---------+
3.指定升序的话,使用asc
select ename,sal from emp order by sal asc;
4.查询员工的名字和薪资,先按照薪资的升序排列,若薪资相同则按照名字的升序排列?
	
	mysql> select ename,sal from emp order by sal asc,ename asc; //sal 在前,起主导作用,只有在sal相等的时候,才会考虑ename的asc的排序.
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | MARTIN | 1250.00 |
    | WARD   | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | FORD   | 3000.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
  也可以这样写,
  mysql> select ename,sal from emp order by 2,1;
  //2就表示根据你写的字段的位置,2就是sal,1就是ename,但不建议这样写,因为字段的顺序很容易发生改变
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | SMITH  |  800.00 |
    | JAMES  |  950.00 |
    | ADAMS  | 1100.00 |
    | MARTIN | 1250.00 |
    | WARD   | 1250.00 |
    | MILLER | 1300.00 |
    | TURNER | 1500.00 |
    | ALLEN  | 1600.00 |
    | CLARK  | 2450.00 |
    | BLAKE  | 2850.00 |
    | JONES  | 2975.00 |
    | FORD   | 3000.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    +--------+---------+
17.综合案例
1.找出工资在1250到3000的员工信息,要求按照薪资降序排列
    mysql> select ename,sal from emp where sal between 1250 and 3000 order by sal desc;
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | FORD   | 3000.00 |
    | SCOTT  | 3000.00 |
    | JONES  | 2975.00 |
    | BLAKE  | 2850.00 |
    | CLARK  | 2450.00 |
    | ALLEN  | 1600.00 |
    | TURNER | 1500.00 |
    | MILLER | 1300.00 |
    | MARTIN | 1250.00 |
    | WARD   | 1250.00 |
    +--------+---------+
    注意:关键字顺序不能变
    select 
    	...
    from
    	...
    where
    	...
    order by
    	....
    以上语句的执行顺序必须掌握
    第一步:from
    第二部:where
    第三步:select
    第四步:排序(排序总是在最后的)
18.数据处理函数
数据处理函数又被称为单行处理函数
	单行处理函数的特点:一个输入对呀一个输出
	和单行处理函数对应的是:多行处理函数(多个输入对应一个输出)
18.1 常见的的单行处理函数有哪些?
	lower 转换小写
		mysql> select lower(ename) from emp;
        +--------------+
        | lower(ename) |
        +--------------+
        | smith        |
        | allen        |
        | ward         |
        | jones        |
        | martin       |
        | blake        |
        | clark        |
        | scott        |
        | king         |
        | turner       |
        | adams        |
        | james        |
        | ford         |
        | miller       |
        +--------------+
	upper 转换大写
	substr 取子串(substr(被截取的字符串,起始下标,截取的长度))
		mysql> select substr(ename,1,3) from emp; //起始下标从一开始,没有0
        +-------------------+
        | substr(ename,1,3) |
        +-------------------+
        | SMI               |
        | ALL               |
        | WAR               |
        | JON               |
        | MAR               |
        | BLA               |
        | CLA               |
        | SCO               |
        | KIN               |
        | TUR               |
        | ADA               |
        | JAM               |
        | FOR               |
        | MIL               |
        +-------------------+
2.查询首字母为A的员工的名字(用substr函数)
    mysql>  select ename from emp where substr(ename,1,1)='A';
    +-------+
    | ename |
    +-------+
    | ALLEN |
    | ADAMS |
    +-------+
    concat 字符串的拼接
    1.将名字和薪资拼接到一块
    mysql> select concat(ename,sal) from emp;
    +-------------------+
    | concat(ename,sal) |
    +-------------------+
    | SMITH800.00       |
    | ALLEN1600.00      |
    | WARD1250.00       |
    | JONES2975.00      |
    | MARTIN1250.00     |
    | BLAKE2850.00      |
    | CLARK2450.00      |
    | SCOTT3000.00      |
    | KING5000.00       |
    | TURNER1500.00     |
    | ADAMS1100.00      |
    | JAMES950.00       |
    | FORD3000.00       |
    | MILLER1300.00     |
    +-------------------+

	2.将名字的首字母小写
     mysql> select concat(lower(substr(ename,1,1)),substr(ename,2)) as result from emp;
    +--------+
    | result |
    +--------+
    | sMITH  |
    | aLLEN  |
    | wARD   |
    | jONES  |
    | mARTIN |
    | bLAKE  |
    | cLARK  |
    | sCOTT  |
    | kING   |
    | tURNER |
    | aDAMS  |
    | jAMES  |
    | fORD   |
    | mILLER |
    +--------+
	length 长度
		获取名字的长度
		mysql> select concat(length(ename),concat('-',ename)) as nameLength from emp;
        +------------+
        | nameLength |
        +------------+
        | 5-SMITH    |	
        | 5-ALLEN    |
        | 4-WARD     |
        | 5-JONES    |
        | 6-MARTIN   |
        | 5-BLAKE    |
        | 5-CLARK    |
        | 5-SCOTT    |
        | 4-KING     |
        | 6-TURNER   |
        | 5-ADAMS    |
        | 5-JAMES    |
        | 4-FORD     |
        | 6-MILLER   |
        +------------+
	trim 去空格
		mysql> select * from emp where ename=trim('  SMITH'); //去除两端空格
    +-------+-------+-------+------+------------+--------+------+--------+
    | EMPNO | ENAME | JOB   | MGR  | HIREDATE   | SAL    | COMM | DEPTNO |
    +-------+-------+-------+------+------------+--------+------+--------+
    |  7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL |     20 |
    +-------+-------+-------+------+------------+--------+------+--------+
	str_to_date 将字符串转换为日期
	date_format 格式化日期
	format 设置千分位
	round 四舍五入
        mysql> select round(123.5674,1) as result from emp;//第二位代表保留小数点后几位.如果是-1,则是保留到十位,向前推.
        +--------+
        | result |
        +--------+
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        |  123.6 |
        +--------+
	rand() 生成随机数
		mysql> select round(rand()*100,0) as result from emp; //生成0-100以内的随机整数
        +--------+
        | result |
        +--------+
        |     27 |
        |     91 |
        |     74 |
        |     99 |
        |     70 |
        |     56 |
        |     67 |
        |     70 |
        |     49 |
        |     35 |
        |     28 |
        |     35 |
        |     89 |
        |     41 |
        +--------+
ifnull 可以将null转换为一个具体值
		计算每个员工的年薪
		年薪 = (月薪+补助)*12
           mysql> select ename,(sal+comm)*12 as yearsal from emp;
        +--------+----------+
        | ename  | yearsal  |
        +--------+----------+
        | SMITH  |     NULL |
        | ALLEN  | 22800.00 |
        | WARD   | 21000.00 |
        | JONES  |     NULL |
        | MARTIN | 31800.00 |
        | BLAKE  |     NULL |
        | CLARK  |     NULL |
        | SCOTT  |     NULL |
        | KING   |     NULL |
        | TURNER | 18000.00 |
        | ADAMS  |     NULL |
        | JAMES  |     NULL |
        | FORD   |     NULL |
        | MILLER |     NULL |
        +--------+----------+
        注意:null只要参与运算,最终结果一定是null,为了避免这个现象的出现,使用		ifnull函数
        	ifnull(数据,被当作那个值?) //如果数据为null时,将null当作哪个值
    mysql> select ename,round((sal+ifnull(comm,0))*12,0) as yearsal 	from emp;
           //如果comm为null则将其看为0对待运算
    +--------+---------+
    | ename  | yearsal |
    +--------+---------+
    | SMITH  |    9600 |
    | ALLEN  |   22800 |
    | WARD   |   21000 |
    | JONES  |   35700 |
    | MARTIN |   31800 |
    | BLAKE  |   34200 |
    | CLARK  |   29400 |
    | SCOTT  |   36000 |
    | KING   |   60000 |
    | TURNER |   18000 |
    | ADAMS  |   13200 |
    | JAMES  |   11400 |
    | FORD   |   36000 |
    | MILLER |   15600 |
case..when..then..when..then..else..end
	跟if else if else差不多
		1.当员工的工作岗位是manager时,工资上调10%,当是salesman时,工资上调50%,其它正常
		mysql> select ename,job,sal oldsal,(case job when 'manager' then sal*1.1 when 'salesman' then sal*1.5 else sal end) as newsal from emp;//打印出oldsal,和计算出newsal
    +--------+-----------+---------+---------+
    | ename  | job       | oldsal  | newsal  |
    +--------+-----------+---------+---------+
    | SMITH  | CLERK     |  800.00 |  800.00 |
    | ALLEN  | SALESMAN  | 1600.00 | 2400.00 |
    | WARD   | SALESMAN  | 1250.00 | 1875.00 |
    | JONES  | MANAGER   | 2975.00 | 3272.50 |
    | MARTIN | SALESMAN  | 1250.00 | 1875.00 |
    | BLAKE  | MANAGER   | 2850.00 | 3135.00 |
    | CLARK  | MANAGER   | 2450.00 | 2695.00 |
    | SCOTT  | ANALYST   | 3000.00 | 3000.00 |
    | KING   | PRESIDENT | 5000.00 | 5000.00 |
    | TURNER | SALESMAN  | 1500.00 | 2250.00 |
    | ADAMS  | CLERK     | 1100.00 | 1100.00 |
    | JAMES  | CLERK     |  950.00 |  950.00 |
    | FORD   | ANALYST   | 3000.00 | 3000.00 |
    | MILLER | CLERK     | 1300.00 | 1300.00 |
    +--------+-----------+---------+---------+
19.当查找字面量时
    mysql> select 'abc' ename from emp; //查找abc字面量时,它会查找14个abc
    +-------+
    | ename |
    +-------+
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    | abc   |
    +-------+
2.当查找1000这个字面量时
    mysql> select 1000 as num from emp;
    +------+
    | num  |
    +------+
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    | 1000 |
    +------+
    注意:select后面可以跟某个表的字段名
20.分组函数(多行处理函数)
多行处理函数的特点:输入多行,最终输出一行
	1.count 计数
	2.sum 求和
	3.avg 平均值
	4.max 最大值
	5.min 最小值
 分组函数在使用时必须先进行分组,然后才能用,
 如果你没有进行分组,整张表默认为一组
     注意:
        1.分组函数自动忽略null,不需要提前对null进行处理.
        2.分组函数中count(*)和count(具体字段)有什么区别?
            count(具体字段),表示统计该字段下所有不为null的总数
            count(*)统计表当中的总行数
		3.分组函数不能够直接使用在where子句中。
        	说完分组查询(group by)之后就明白了.
        4.分组函数可以一起用
        mysql> select max(sal),min(sal),avg(sal),sum(sal) from emp;
        +----------+----------+-------------+----------+
        | max(sal) | min(sal) | avg(sal)    | sum(sal) |
        +----------+----------+-------------+----------+
        |  5000.00 |   800.00 | 2073.214286 | 29025.00 |
        +----------+----------+-------------+----------+
21.分组查询(重要)
1.什么是分组查询?
	在实际应用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作,这个时候我们需要使用分组查询,怎么进行分组查询呢?
	select
		....
	from
		....
	group by
		....
21.1将之前的关键字全部组合在一起,看他们的执行顺序?
	select
		...
	where
		...
	group by
		...
	order by
		...
	以上关键字的顺序不能颠倒,需要记忆!!
		执行顺序是什么?
			1.from
			2.where
			3.group by
			4.select
			5.order by
		为什么分组函数不能直接使用在where后面?
			select ename,sal from emp where sal>min(sal)?报错
			因为分组函数使用的时候,必须先进行分组之后才能使用
			where(第二个执行)执行的时候,还没有进行分组(第三个执行),所以where后面不能出现分组函数
21.2找出每个工作岗位的工资和?
	mysql>
    select job,sum(sal) 
    from emp 
    group by job;
    +-----------+----------+
    | job       | sum(sal) |
    +-----------+----------+
    | ANALYST   |  6000.00 |
    | CLERK     |  4150.00 |
    | MANAGER   |  8275.00 |
    | PRESIDENT |  5000.00 |
    | SALESMAN  |  5600.00 |
    +-----------+----------+
    如果这样写:
    	select ename,job,sum(sal) 
    from emp 
    group by job; //这样没有意义,因为名字有14个,job有五个,不能进行整合
   注意:
   	在一条select语句当中,如果有group by语句的话,
   	select后面只能跟: 参加分组的字段,以及分组函数,
   	其它一律不能跟
21.3找出每个部门的最高薪资?
	mysql> select deptno,max(sal) from emp group by deptno;
    +--------+----------+
    | deptno | max(sal) |
    +--------+----------+
    |     10 |  5000.00 |
    |     20 |  3000.00 |
    |     30 |  2850.00 |
    +--------+----------+
21.4找出每个部门,不同工作岗位的最高薪资?
	两个分组条件,1.部门分组 2.工作岗位再进行分组,最后输出全部符合条件的
	mysql> 
	select max(sal),job,deptno 
	from emp 
	group by deptno,job; //根据部门,然后再根据岗位进行分组,然后再找出最高工资进行输出.
    +----------+-----------+--------+
    | max(sal) | job       | deptno |
    +----------+-----------+--------+
    |  1300.00 | CLERK     |     10 |
    |  2450.00 | MANAGER   |     10 |
    |  5000.00 | PRESIDENT |     10 |
    |  3000.00 | ANALYST   |     20 |
    |  1100.00 | CLERK     |     20 |
    |  2975.00 | MANAGER   |     20 |
    |   950.00 | CLERK     |     30 |
    |  2850.00 | MANAGER   |     30 |
    |  1600.00 | SALESMAN  |     30 |
    +----------+-----------+--------+
21.5 找出每个部门的最高薪资,要求显示最高工资大于三千的?(使用having可以分完组后进行过滤),having不能单独使用,必须结合group by,并且having不能代替where
    mysql> select max(sal),deptno from emp group by deptno having max(sal)>3000;
    +----------+--------+
    | max(sal) | deptno |
    +----------+--------+
    |  5000.00 |     10 |
    +----------+--------+
   第二种解法:
   	mysql> select max(sal),deptno from emp where sal>3000 group by deptno; //先用where进行过滤,把低于3000的过滤出去,然后再进行分组,也可以
+----------+--------+
| max(sal) | deptno |
+----------+--------+
|  5000.00 |     10 |
+----------+--------+
	注意:where和having,能用where先用where.
21.6找出每个人部门的平均工资,并且平均薪资高于2500?
	mysql> select avg(sal),deptno from emp group by deptno having avg(sal)>2500; //这个就只能用having了
+-------------+--------+
| avg(sal)    | deptno |
+-------------+--------+
| 2916.666667 |     10 |
+-------------+--------+
22.大总结(单表)
select
	...
from
	...
where
	...
geoup by
	...
having
	...
order by
	...
		以上关键字只能按照上方的顺序来,不能颠倒
执行顺序为:
	1.from
	2.where
	3.group by
	4.having
	5.select
	6.order by
从某张表中查询数
先经过where条件筛选出有价值的数据,
对这些数据再进行分组,
分组之后可以用having进行继续筛选
最后排序输出
22.1 找出每个岗位平均薪资,要求显示平均薪资大于1500,除manager之外,要求平均薪资降序排列.
	mysql> select avg(sal),job from emp where job != 'manager' group by job having avg(sal)>1500 order by avg(sal) desc;//查询平均工资,和job,
	条件是job不是manager的,分组为job,子条件为平均工资大于1500,排序为平均工资降序.
+-------------+-----------+
| avg(sal)    | job       |
+-------------+-----------+
| 5000.000000 | PRESIDENT | //首席执行官岗位
| 3000.000000 | ANALYST   | //分析师
+-------------+-----------+
23.去除重复记录
将查询结果去重,使用关键字distinct.不会对原表产生影响,只能出现所有字段的最前方.
    mysql> select count(distinct(job)) as numDis from emp;
    +--------+
    | numDis |
    +--------+
    |      5 |
    +--------+
24.连接查询(超级重点)
从一张表中单独查询,称为单表查询
emp和dept表联合起来查询数据,从emp标志取员工名字,从部门表中取部门名字
这种跨表查询,多张表联合起来查询数据,被称为连接查询.
1.连接查询的分类?
	根据语法的年代分类:
		sql92: 1992年出现的语法
		sql99:1999年出现的语法
		重点学习99.
		表连接方式分类?
			内连接:
				等值连接
				非等值连接
				自链接
			外连接:
				左外连接(左连接)
				右外连接(右连接)
			全连接
24.2当两张表进行连接查询时,没有任何条件的限制,会发生什么样的现象?
	会发生笛卡尔积现象,没有任何限制时,查询的数量是两张表数量的乘积.
	1.怎么避免笛卡尔积现象?
		连接时加条件,满足条件的记录筛选出来.
	24.2.1查询每个员工做所在部门的名称?
		mysql> select ename,dname from emp,dept where emp.deptno = dept.deptno; //结果为14条结果
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+
    注意:匹配的结果少了,但匹配的次数不会减少.
   	并且效率不高,因为ename会去dept找,dname会区emp找.所以为了提高效率,可以将其查找的加上表名:
   	//给表起别名为e,d
   	mysql>select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno; //sql92
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+
25内连接之等值连接
1.找出员工的部门,输出员工名字和部门名字
select
    -> e.ename,d.dname
    -> from
    -> emp e
    ->(inner可省略) join
    -> dept d
    -> on
    -> e.deptno=d.deptno; //等值连接,条件是等量关系
    //join on sql99方法
    sql92缺点:结构不清晰,将表的连接和后期进一步筛选的条件,都放到了where后面.
    sql99的优点,表连接条件是独立的,连接之后,如果还需要进一步筛选,再往后添加where即可
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+
	注意;sql99的语法
	select
		...
	from
		a
	join
		b
	on
		a和b的连接条件
	where
		筛选条件
26.内连接之非等值连接
1.找出每个员工的薪资等级,要求显示员工名 薪资 薪资等级?
	mysql> select e.ename,e.sal,s.grade from emp e join
    salgrade s
    on
    e.sal between s.losal and  s.hisal;
    +--------+---------+-------+
    | ename  | sal     | grade |
    +--------+---------+-------+
    | SMITH  |  800.00 |     1 |
    | ALLEN  | 1600.00 |     3 |
    | WARD   | 1250.00 |     2 |
    | JONES  | 2975.00 |     4 |
    | MARTIN | 1250.00 |     2 |
    | BLAKE  | 2850.00 |     4 |
    | CLARK  | 2450.00 |     4 |
    | SCOTT  | 3000.00 |     4 |
    | KING   | 5000.00 |     5 |
    | TURNER | 1500.00 |     3 |
    | ADAMS  | 1100.00 |     1 |
    | JAMES  |  950.00 |     1 |
    | FORD   | 3000.00 |     4 |
    | MILLER | 1300.00 |     2 |
    +--------+---------+-------+
27.内连接之自连接
查询员工的上级领导,要求显示员工名个对应的领导名?
    mysql> select e.ename,e2.ename Pname from emp e
        -> join emp e2
        -> on
        -> e.mgr = e2.empno; //员工的领导编号等于领导的员工编号
    +--------+-------+
    | ename  | Pname |
    +--------+-------+
    | SMITH  | FORD  |
    | ALLEN  | BLAKE |
    | WARD   | BLAKE |
    | JONES  | KING  |
    | MARTIN | BLAKE |
    | BLAKE  | KING  |
    | CLARK  | KING  |
    | SCOTT  | JONES |
    | TURNER | BLAKE |
    | ADAMS  | SCOTT |
    | JAMES  | BLAKE |
    | FORD   | JONES |
    | MILLER | CLARK |
    +--------+-------+
    	以上就是内连接的自连接,技巧:一张表看成两张表
28.外连接
1.找出员工所在部门,并且显示员工姓名和(全部)部门
mysql> select e.ename,d.dname from emp e
    -> right (outer可省略) join //右外连接,就是将join右边的为主表,left(左连接)反之.
    
    -> dept d
    -> on
    -> e.deptno = d.deptno;
    //right代表,将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关练查询左边的表
    而外连接的特点,是完成能够匹配上这个条件的数据查询出来.两张表或几张表没有主次关系
+--------+------------+
| ename  | dname      |
+--------+------------+
| CLARK  | ACCOUNTING |
| KING   | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH  | RESEARCH   |
| JONES  | RESEARCH   |
| SCOTT  | RESEARCH   |
| ADAMS  | RESEARCH   |
| FORD   | RESEARCH   |
| ALLEN  | SALES      |
| WARD   | SALES      |
| MARTIN | SALES      |
| BLAKE  | SALES      |
| TURNER | SALES      |
| JAMES  | SALES      |
| NULL   | OPERATIONS |
+--------+------------+
        注意:内连接与外连接的区别就是有没有right与left关键字,有就是外连接.
   外连接的查询结果条数一定是>= 内连接的查询结果条数
	mysql> select e.ename '员工名',e2.ename '领导名'
    from emp as e
        left join
           emp e2
           on
           e.mgr =e2.empno;
    +--------+--------+
    | 员工名  | 领导名  |
    +--------+--------+
    | SMITH  | FORD   |
    | ALLEN  | BLAKE  |
    | WARD   | BLAKE  |
    | JONES  | KING   |
    | MARTIN | BLAKE  |
    | BLAKE  | KING   |
    | CLARK  | KING   |
    | SCOTT  | JONES  |
    | KING   | NULL   |
    | TURNER | BLAKE  |
    | ADAMS  | SCOTT  |
    | JAMES  | BLAKE  |
    | FORD   | JONES  |
    | MILLER | CLARK  |
    +--------+--------+
29.三张表,四张表的连接
语法:
	select
		...
	from
		a
	join
		b
	on
		a和b的连接条件
	join
		c
	on
		a和c的连接条件
	join
		d
	on
		a和d的连接条件
案例:(三张表进行连接)
	找出每个员工的部门名称以及工资等级,要求显示员工名\部门名\薪资\薪资等级?
mysql> select e.ename,e.sal,d.dname,s.grade from emp as e
    ->     join dept as d
    ->     on
    ->     e.deptno = d.deptno
    ->     join salgrade as s
    ->     on
    ->     e.sal between s.losal and s.hisal;
+--------+---------+------------+-------+
| ename  | sal     | dname      | grade |
+--------+---------+------------+-------+
| SMITH  |  800.00 | RESEARCH   |     1 |
| ALLEN  | 1600.00 | SALES      |     3 |
| WARD   | 1250.00 | SALES      |     2 |
| JONES  | 2975.00 | RESEARCH   |     4 |
| MARTIN | 1250.00 | SALES      |     2 |
| BLAKE  | 2850.00 | SALES      |     4 |
| CLARK  | 2450.00 | ACCOUNTING |     4 |
| SCOTT  | 3000.00 | RESEARCH   |     4 |
| KING   | 5000.00 | ACCOUNTING |     5 |
| TURNER | 1500.00 | SALES      |     3 |
| ADAMS  | 1100.00 | RESEARCH   |     1 |
| JAMES  |  950.00 | SALES      |     1 |
| FORD   | 3000.00 | RESEARCH   |     4 |
| MILLER | 1300.00 | ACCOUNTING |     2 |
+--------+---------+------------+-------+
2.案例:
	找出每个员工的部门名称以及工资等级,还有上级领导,要求显示员工名\领导名\部门名\薪资\薪资等级?
	select 
	e.ename,e2.ename Pname,e.sal,d.dname,s.grade 
	from emp e
	left join emp e2
	on
	e.mgr = e2.empno
	join dept d
	on
	e.deptno = d.deptno
    join salgrade s
    on
    e.sal between s.losal and s.hisal;
    +--------+-------+---------+------------+-------+
    | ename  | Pname | sal     | dname      | grade |
    +--------+-------+---------+------------+-------+
    | SMITH  | FORD  |  800.00 | RESEARCH   |     1 |
    | ALLEN  | BLAKE | 1600.00 | SALES      |     3 |
    | WARD   | BLAKE | 1250.00 | SALES      |     2 |
    | JONES  | KING  | 2975.00 | RESEARCH   |     4 |
    | MARTIN | BLAKE | 1250.00 | SALES      |     2 |
    | BLAKE  | KING  | 2850.00 | SALES      |     4 |
    | CLARK  | KING  | 2450.00 | ACCOUNTING |     4 |
    | SCOTT  | JONES | 3000.00 | RESEARCH   |     4 |
    | KING   | NULL  | 5000.00 | ACCOUNTING |     5 |
    | TURNER | BLAKE | 1500.00 | SALES      |     3 |
    | ADAMS  | SCOTT | 1100.00 | RESEARCH   |     1 |
    | JAMES  | BLAKE |  950.00 | SALES      |     1 |
    | FORD   | JONES | 3000.00 | RESEARCH   |     4 |
    | MILLER | CLARK | 1300.00 | ACCOUNTING |     2 |
    +--------+-------+---------+------------+-------+
30.子查询?
30.1什么是子查询?
	select语句中嵌套select语句,被嵌套的select语句被称为子查询.
30.2子查询都可以出现在哪里呢?
	select
		..(select).
	from
		...(select)
	where
		..(select).
30.3 where子句中出现子查询
	案例:
		找出比最低工资高的员工的姓名,薪资
	mysql> select ename,sal from emp where sal>(select min(sal) from emp); //子查询先执行
    +--------+---------+
    | ename  | sal     |
    +--------+---------+
    | ALLEN  | 1600.00 |
    | WARD   | 1250.00 |
    | JONES  | 2975.00 |
    | MARTIN | 1250.00 |
    | BLAKE  | 2850.00 |
    | CLARK  | 2450.00 |
    | SCOTT  | 3000.00 |
    | KING   | 5000.00 |
    | TURNER | 1500.00 |
    | ADAMS  | 1100.00 |
    | JAMES  |  950.00 |
    | FORD   | 3000.00 |
    | MILLER | 1300.00 |
    +--------+---------+
30.4.from中的子查询,可以将子查询的查询结果当作一个临时表(技巧).
案例:
	找出每个岗位的平均工资的薪资等级.
	1.select avg(sal),job from emp group by job;
	select 
		s.grade,t.* 
	from 
		salgrade s
	join
		(select avg(sal) as avgSal,job from emp group by job) as t
    on  
    	avgSal between s.losal and s.hisal
   	order by
      	s.grade asc;
    +-------+-------------+-----------+
    | grade | avgSal      | job       |
    +-------+-------------+-----------+
    |     1 | 1037.500000 | CLERK     |
    |     2 | 1400.000000 | SALESMAN  |
    |     4 | 3000.000000 | ANALYST   |
    |     4 | 2758.333333 | MANAGER   |
    |     5 | 5000.000000 | PRESIDENT |
    +-------+-------------+-----------+
30.5.select后面出现的子查询(这个内容不需要掌握,了解即可!!!)
   案例:
      找出每个员工的部门名称,要求显示员工名,部门名?
 mysql> select e.ename,d.dname from emp e
    join dept d
    on
    e.deptno = d.deptno;
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | CLARK  | ACCOUNTING |
    | KING   | ACCOUNTING |
    | MILLER | ACCOUNTING |
    | SMITH  | RESEARCH   |
    | JONES  | RESEARCH   |
    | SCOTT  | RESEARCH   |
    | ADAMS  | RESEARCH   |
    | FORD   | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | TURNER | SALES      |
    | JAMES  | SALES      |
    +--------+------------+       
第二种解决办法.select子查询
mysql> 
select e.ename,
(select d.dname,deptno from dept d where e.deptno=d.deptno) dname 
from 
emp e;
//注意:对于select后面的子查询来说,这个子查询只能返回一个字段,
    +--------+------------+
    | ename  | dname      |
    +--------+------------+
    | SMITH  | RESEARCH   |
    | ALLEN  | SALES      |
    | WARD   | SALES      |
    | JONES  | RESEARCH   |
    | MARTIN | SALES      |
    | BLAKE  | SALES      |
    | CLARK  | ACCOUNTING |
    | SCOTT  | RESEARCH   |
    | KING   | ACCOUNTING |
    | TURNER | SALES      |
    | ADAMS  | RESEARCH   |
    | JAMES  | SALES      |
    | FORD   | RESEARCH   |
    | MILLER | ACCOUNTING |
    +--------+------------+
31.union合并查询结果集
查询工作岗位是manager和salesman的员工?
mysql> select ename,job from emp where job='manager'
    -> union
    -> select ename,job from emp where job='salesman';
    //使用union进行查询结果的合并,(union的效率的高一些),union把乘法变成了加法.
    注意:union在进行结果集合并的时候,查询的结果列数得相同,在mysql中类型不一定一样,但在oracle中就会报错,oracle必须使其列数和类型都相同才能合并
+--------+----------+
| ename  | job      |
+--------+----------+
| JONES  | MANAGER  |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
32.limit(很重要)
limit的作用:将查询结果集的一部分取出来,通常使用在分页的查询当中.
limit的用法? [startIndex:起始下标],length:数量
	1.按照薪资降序,取出排名在前五名的员工?
		select ename,sal 
		from emp 
		order by sal desc 
		limit 0,5;
		+-------+---------+
        | ename | sal     |
        +-------+---------+
        | KING  | 5000.00 |
        | SCOTT | 3000.00 |
        | FORD  | 3000.00 |
        | JONES | 2975.00 |
        | BLAKE | 2850.00 |
        +-------+---------+
注意:在mysql中limit是在order by之后执行
	2.取出工资排名在3-5名的员工?
		select ename,sal from emp
		order by sal desc
		limit 2,3; //3-5名,一共是3,4,5,三名,从三开始,也就是下标2,
        +-------+---------+
        | ename | sal     |
        +-------+---------+
        | FORD  | 3000.00 |
        | JONES | 2975.00 |
        | BLAKE | 2850.00 |
        +-------+---------+
	3.去除工资排名在5-9名的数据?
		select ename,sal from emp order by sal desc limit 4,5;
		+--------+---------+
        | ename  | sal     |
        +--------+---------+
        | BLAKE  | 2850.00 |
        | CLARK  | 2450.00 |
        | ALLEN  | 1600.00 |
        | TURNER | 1500.00 |
        | MILLER | 1300.00 |
        +--------+---------+

33分页
每页显示三条记录
	第一页: limit 0,3  [0,1,2]
	第二页:limit 3,3   [3,4,5]
	第三页:limit 6,3   [6,7,8]
每页显示pageSize条数据
第pageNo页: limt (pageNo-1)*pageSize,pageSize
34.关于DQL的大总结
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
34个作业题:		

三.1、DDL语句(数据类型)

1.创建表DDL语句(create,drop alter)
1.create table 表名(
	字段名1 数据类型,
	字段名2 数据类型,
	字段名3 数据类型
);
	表名建议以t_ 或者tbl_开始,可读性强
2.关于mysql中的数据类型?
varchar(255) =>可变长度的字符串,比较智能,节省空间,会根据实际的数据成都动态的娥分配空间.
	优点:节省空间
	缺点:动态的分配空间,速度慢
char(255)    =>固定长度字符串,不管实际的数据长度是多少,分配固定的空间去存储数据.
	优点:效率高
	缺点:可能会导致空间的浪费.
	性别采用 char(..)
int(11)	=>整数型
bigint  =>长整型 java的long
float   => 单精度浮点型数据
double  =>双精度浮点型数据
date    => 短日期类型
datetmie=> 长日期类型
clob    =>
	字符大对象
		最多可以存储4G的字符串
		比如:才能出一篇文章,存储一篇说明
		超过255的字符的都要采用clob字符大对象来存储
blob    =>
	二进制大对象
	binary large Object
	著名来存储图片,声音,视频等流媒体数据
	往BLOB字段插入数据的时候,得用IO流才行
1.2t_move 电影表(专门存储电影信息的)
 编号       名字           描述
no(bigint) name(varchar)  description(clob) 
10000      长津湖           这是一个战争类型的大型电影,非常nice
上映日期			时长		海报         类型
playtime(date) time(double) image(blob) type(char)
2021-10-1          2.2        ...       '1'
1.3创建学生表
学号,姓名,年龄,性别邮箱地址
create table t_student(
	no int,
	name varchar(255),
	age int(3),
	gender char(1),
	email varchar(255)
);

删除表:
	drop table t_student; //当这张表不存在的时候会报错
	drop table  if exists t_student; //如果存在删除!

三.2 DML(数据操作语句)

1.4插入数据==(insert)(DML)==
insert into 表名(`字段`1,字段2,字段3) values(值1,值2,值3);
字段和值一一对应,数量要对应,数据类型也要对应.
insert into t_student(no,name,age,gender,email) values(1,'zhangqiankang',20,'m','2315119543@qq.com');
insert into t_student(email,no,name,age,gender) values('577934719@qq.com',2,'ymm',20,'f');
insert into t_student(no) values(3);
insert into t_student(name) values('ymmzqk')
注意:insert 只要执行成功了,就会增加一条记录,
    没有给其它字段指定值的话,默认值是NULL.
删除表再创建.
drop tables if exists t_student;
create table t_student(
	no int,
    name varchar(32),
    age int(3),
    gender char(1)  default 'm', //默认值
    email varchar(255)
);
insert into t_student(no) values(1);
1.insert语句中的字段名可以省略嘛?
	insert table t_student values(2); //报错
	注意:前面的字段名省略的话,相当于都写上了,所以值也都要写上!
	insert into t_student values(2,'lisi',20,'f','123456@qq.com'); //字段名都不写,所以相当于全都写上.
1.5insert插入日期
日期函数:
	str_to_date:将字符串varchar转换为date类型
	date_format:将date类型转换为具有一定格式的varchar字符串类型
	create table t_user(
		id int,
		name varchar(32),
		birth date,
		create_time bigint
	);
	注意:数据库中的有一条命名规范:
		所有的娥标识符都是全部小写,单词和单词之间使用下划线进行衔接.
	insert into t_user(id,name,birth,create_time) values(1,'lisi',str_to_date('1999-03-10','%Y-%m-%d'),20220322);
	mysql的日期格式:
		%Y 年
		%m 月
		%d 日
		%h 时
		%i 分
		%s 秒
		str_to_date函数可以把字符串varchar转换成date类型数据,通常使用在insert方面,因为插入的时候需要将一个日期格式的数据,需要通过该函数将字符串转化为date
	好消息,如果你提供的日期字符串是固定的这个格式,str_to_date就不需要了!!
	%Y-%m-%d z这个格式
	insert into t_user(id,name,birth,create_time) values(2,'zhangsan','2001-05-22',20220322);
2.在查询日期时,能以特定的格式呈现嘛?
	可以用date_format来进行格式化
	select name,date_format(birth,'%d/%m/%Y') datebirth from t_user; //通过使用date_format来转换为字符串.
	date_format怎么用?
		date_format(日期类型数据,'日期格式')
		这个函数通常使用在查询方面.设置展示的日期格式.
	若日期格式不适应date_format转换可以输出嘛?
	select name,birth from t_user;
    +----------+------------+
    | name     | birth      |
    +----------+------------+
    | lisi     | 1999-03-10 |
    | zhangsan | 2001-05-22 |
    +----------+------------+
    这里默认是进行了日期格式转换.自动将date类型转换成了varchar类型.
    总结:str_to_date可以将字符串转换为日期类型,date_format可以将日期格式转换为字符串
1.6date和datetime区别?
date是短日期,只包括年月日
datetime是长日期,包括年月日时分秒的娥信息
drop table if exists t_user;
create table t_user(
	id int,
	name varchar(32),
	birth date,    
	create_time datetime
);
注意:mysql 短日期默认格式:%Y-%m-%d.
 长日期格式: %Y-%m-%d %h:%i:%s
insert into t_user(id,name,birth,create_time) values(1,'lisi','2002-02-22','2022-03-22 22:16:45');

在mysql当中怎么获取当前时间呢?
    用now() 方法
insert into t_user(id,name,birth,create_time) values(2,'caobie','2001-05-12',now());
1.7改 update(DML)
update 表名 set 字段1=值1,字段2=值2 where 条件;
注意: 没有条件限制会导致所有数据全部更新.
update t_user set name= 'zhengtianyi',birth='2000-02-29',create_time = now() where id =1;
1.8 delete删除数据(DML)
delete from 表名 where 条件;
	若无条件,则整张表都会被删除!!!
	delete from t_user where id = 2;

四、34道作业题

1.取得每个部门最高薪水的人员名称
1.1select deptno,max(sal) as maxsal from emp group by deptno;
    +--------+---------+
    | deptno | maxsal  |
    +--------+---------+
    |     10 | 5000.00 |
    |     20 | 3000.00 |
    |     30 | 2850.00 |
    +--------+---------+
    //取得每个部门最高的是多少.
1.2.select e.ename,t.*  from emp e join (select deptno,max(sal) as maxsal from emp group by deptno) t
on e.deptno = t.deptno and e.sal = t.maxsal;
2.哪些人的薪水在部门的平均薪水之上?
2.1 select avg(sal) from emp group by deptno;
    +-------------+
    | avg(sal)    |
    +-------------+
    | 2916.666667 |
    | 2175.000000 |
    | 1566.666667 |
    +-------------+
2.2 select e.ename,e.sal from emp e join (select deptno,avg(sal) as avgsal from emp group by deptno) t on
e.deptno = t.deptno and e.sal>t.avgsal;
    +-------+---------+
    | ename | sal     |
    +-------+---------+
    | ALLEN | 1600.00 |
    | JONES | 2975.00 |
    | BLAKE | 2850.00 |
    | SCOTT | 3000.00 |
    | KING  | 5000.00 |
    | FORD  | 3000.00 |
    +-------+---------+
3.取得部门中(所有人的)平均的薪水等级
select grade,sal,deptno from emp join salgrade s on
	sal between s.losal and s.hisal; //先找出每个人的薪资等级
+-------+---------+--------+
| GRADE | sal     | deptno |
+-------+---------+--------+
|     1 |  800.00 |     20 |
|     3 | 1600.00 |     30 |
|     2 | 1250.00 |     30 |
|     4 | 2975.00 |     20 |
|     2 | 1250.00 |     30 |
|     4 | 2850.00 |     30 |
|     4 | 2450.00 |     10 |
|     4 | 3000.00 |     20 |
|     5 | 5000.00 |     10 |
|     3 | 1500.00 |     30 |
|     1 | 1100.00 |     20 |
|     1 |  950.00 |     30 |
|     4 | 3000.00 |     20 |
|     2 | 1300.00 |     10 |
+-------+---------+--------+
select avg(t.grade),deptno from (select grade,sal,deptno from emp join salgrade s on
	sal between s.losal and s.hisal) t group by t.deptno;
	//然后再根据部门求得薪资等级的平均值
	+--------------+--------+
    | avg(t.grade) | deptno |
    +--------------+--------+
    |       3.6667 |     10 |
    |       2.8000 |     20 |
    |       2.5000 |     30 |
    +--------------+--------+
4、不准用组函数(Max),取得最高薪水(给出两种解决方案)
第一种:select sal from emp order by sal desc limit 1;//降序,取1.
    +---------+
    | sal     |
    +---------+
    | 5000.00 |
    +---------+
第二种:表连接
select sal from emp where sal not in (select distinct a.sal from emp a join emp b on
	a.sal<b.sal
);//查询sal,并且条件是sal不在子查询内,而子查询是,令两个emp表(a,b)连接,并且条件为a的sal小于b的sal的 a的sal,并去重,所以只有最大的不会小于自己表中的sal.
5、取得平均薪水最高的部门的部门编号(至少给出两种解决方案)
select avg(sal) as avgsal,deptno from emp group by deptno;
select max(t.avgsal) Tsal,d.deptno from (select avg(sal) as avgsal,deptno from emp group by deptno) t join dept d on 
d.deptno = t.deptno;
    +-------------+--------+
    | Tsal        | deptno |
    +-------------+--------+
    | 2916.666667 |     10 |
    +-------------+--------+
第二种:将查询出来部门的平均工资,进行降序排序,然后取出第一个就是最高的那个,然后跟部门表进行连接,取出和部门编号相同的即可
select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1;
	select t.avgsal Tsal_tow,d.deptno from (select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1) t join dept d on 
d.deptno = t.deptno;
    +-------------+--------+
    | Tsal_tow    | deptno |
    +-------------+--------+
    | 2916.666667 |     10 |
    +-------------+--------+
6.取得平均薪水最高的部门的部门名称
select avg(sal) avgsal_T from emp group by deptno order by avgsal_T desc limit 1;
select 
	d.dname 
from 
	dept d 
join 
	(select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal desc limit 1) as t
on
	d.deptno = t.deptno;
//	首先查询出来平均薪资最高的部门编号,然后再再进行表连接筛选出编号相同的部门名字。
	+------------+
    | dname      |
    +------------+
    | ACCOUNTING |
    +------------+
7.求平均薪水的等级最低的部门的部门名称
select avg(sal) avgsal,deptno from emp group by deptno order by avgsal asc limit 1; //先查出最低的平均工资编号
select 
	d.dname 
from 
	dept d 
join 
	(select avg(sal) as avgsal,deptno from emp group by deptno order by avgsal asc limit 1) as t
on
	d.deptno = t.deptno;//然后再根据编号查出部门
	+-------+
    | dname |
    +-------+
    | SALES |
    +-------+
8.取得比普通员工(员工代码没有在mgr字段上出现的)的最高薪水还要高的领导人姓名
1.员工代码没有在mgr上面也就是 not in,然后再取出这其中最高的工资为多少:
	1.取出mgr不为null的.
	select mgr from emp where mgr is not null;
	select max(sal) from emp where empno not in (select mgr from emp where mgr is not null); //找出工人的最高薪资
	select ename,sal from emp,(select max(sal) maxsal from emp where empno not in (select mgr from emp where mgr is not null)) t where sal>t.maxsal; //然后找出领导人姓名,条件是工资大于那个工人最高工资.
		+-------+---------+
        | ename | sal     |
        +-------+---------+
        | JONES | 2975.00 |
        | BLAKE | 2850.00 |
        | CLARK | 2450.00 |
        | SCOTT | 3000.00 |
        | KING  | 5000.00 |
        | FORD  | 3000.00 |
        +-------+---------+
9.取得薪水最高的前五名员工
select ename,sal from emp order by sal desc limit 0,5;
    +-------+---------+
    | ename | sal     |
    +-------+---------+
    | KING  | 5000.00 |
    | SCOTT | 3000.00 |
    | FORD  | 3000.00 |
    | JONES | 2975.00 |
    | BLAKE | 2850.00 |
    +-------+---------+
10、取得薪水最高的第六到第十名员工
select ename,sal from emp order by sal desc limit 5,5;
+--------+---------+
| ename  | sal     |
+--------+---------+
| CLARK  | 2450.00 |
| ALLEN  | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
| MARTIN | 1250.00 |
+--------+---------+
//直接limit 5,5 从五开始,数量为5
11、取得最后入职的5名员工
select ename,hiredate,date_format(hiredate,'%Y%m%d') dateformathire from emp order by date_format(hiredate,'%Y%m%d') desc limit 5; //先将日期格式化,然后再将其排序降序输出,条数为5个
+--------+------------+--------------------------------+
| ename  | hiredate   | date_format(hiredate,'%Y%m%d') |
+--------+------------+--------------------------------+
| ADAMS  | 1987-05-23 | 19870523                       |
| SCOTT  | 1987-04-19 | 19870419                       |
| MILLER | 1982-01-23 | 19820123                       |
| FORD   | 1981-12-03 | 19811203                       |
| JAMES  | 1981-12-03 | 19811203                       |
+--------+------------+--------------------------------+
12、取得每个薪水等级有多少员工
select s.grade,count(s.grade) Gradenum from emp e join salgrade s on
e.sal between s.losal and s.hisal group by s.grade;
    +-------+----------+
    | grade | Gradenum |
    +-------+----------+
    |     1 |        3 |
    |     2 |        3 |
    |     3 |        2 |
    |     4 |        5 |
    |     5 |        1 |
    +-------+----------+
13.面试题(学生,课程,学生选课)
//课程表
+------+----------+----------+
| CNO  | CNAME    | CTEACHER |
+------+----------+----------+
| 1    | yuwen    | zhang    |
| 2    | zhengzhi | wang     |
| 3    | yingyu   | li       |
| 4    | shuxue   | zhao     |
| 5    | wuli     | liming   |
+------+----------+----------+
//学生表
+------+----------+
| SNO  | SNAME    |
+------+----------+
| 1    | student1 |
| 2    | student2 |
| 3    | student3 |
| 4    | student4 |
+------+----------+
//学生选课表
+------+------+---------+
| SNO  | CNO  | SCGRADE |
+------+------+---------+
| 2    | 1    | 60      |
| 2    | 3    | 60      |
| 2    | 4    | 60      |
| 2    | 5    | 40      |
| 3    | 3    | 80      |
| 1    | 1    | 40      |
| 1    | 2    | 30      |
| 1    | 4    | 80      |
| 1    | 5    | 60      |
+------+------+---------+
1.找出没选过“黎明”老师的所有学生姓名
select distinct sname from s where
sno not in (select sno from sc where cno=(select cno from c where cteacher='liming'));
    +----------+
    | sname    |
    +----------+
    | student3 |
    | student4 |
    +----------+	
    /先通过liming找出对应的课程号,然后通过课程号找出选这个课程号的学号,然后再输出不是这些学号的学生姓名
 2.列出 2 门以上(含 2 门)不及格学生姓名及平均成绩。
 select count(scgrade) as rejgradenum,sno from sc where scgrade<60 group by SNO  having rejgradenum>=2;  
 //先找出不及格两门以上的学生的学号
 select sname,avg(sc.scgrade) from s join (select count(scgrade) as rejgradenum,sno from sc where scgrade<60 group by SNO having rejgradenum>=2) t
 on
 t.sno =s.sno
join sc
on 
sc.sno  = t.sno;
//然后再查询学生的姓名,及他全部的成绩的平均成绩,所以t临时表和s可以查到学生姓名,再连接sc表可以将这个学生的全部成绩求平均.
+----------+-----------------+
| sname    | avg(sc.scgrade) |
+----------+-----------------+
| student1 |            52.5 |
+----------+-----------------+
3.即学过 1 号课程又学过 2 号课所有学生的姓名。
	select sno from sc where cno='1' ;
	select sno from sc where cno='2' ;
	//先查询出等于课程号等于1的学号,
	//再查询出课程号等于2的学生的学号
	select s.sname from s join  (select sno from sc where cno='1') a 
	on
	s.sno = a.sno
	join(select sno from sc where cno='2') b on  a.sno=b.sno;
	//查询课程号为1的学号和课程号为2的学号进行相等,抽取出学号,然后确定出选择一又选择二的学号,然后用确定的学号对s学生表进行匹配姓名,然后输出
14.列出所有员工及领导的姓名
select e.ename,ifnull(m.ename,'没有上级') from emp e left join emp m
on
e.mgr = m.empno;
//两张emp员工表进行连接,条件是e的mgr属性值等于m.empno属性值
    +--------+----------------------------+
    | ename  | ifnull(m.ename,'没有上级')  |
    +--------+----------------------------+
    | SMITH  | FORD                       |
    | ALLEN  | BLAKE                      |
    | WARD   | BLAKE                      |
    | JONES  | KING                       |
    | MARTIN | BLAKE                      |
    | BLAKE  | KING                       |
    | CLARK  | KING                       |
    | SCOTT  | JONES                      |
    | KING   | 没有上级                   	|
    | TURNER | BLAKE                      |
    | ADAMS  | SCOTT                      |
    | JAMES  | BLAKE                      |
    | FORD   | JONES                      |
    | MILLER | CLARK                      |
    +--------+----------------------------+
15、列出受雇日期早于其直接上级的所有员工的编号,姓名,部门名称
select mgr from emp;
select 		    	 							t.empno,t.deptno,t.ename
from 
	emp e 
join 
	(select empno ,deptno,ename,mgr,date_format(t1.hiredate,'%Y%m%d') as tdate from emp t1) t 
on
	e.empno  = t.mgr and t.tdate<date_format(e.hiredate,'%Y%m%d');
	//先查询出来比上级早的员工姓名部门编号
	+-------+--------+-------+
    | empno | deptno | ename |
    +-------+--------+-------+
    |  7369 |     20 | SMITH |
    |  7499 |     30 | ALLEN |
    |  7521 |     30 | WARD  |
    |  7566 |     20 | JONES |
    |  7698 |     30 | BLAKE |
    |  7782 |     10 | CLARK |
    +-------+--------+-------+

select 
	m.empno,m.ename,d.dname 
from 
	dept d 
join 
(
	select 		    	 
		t.empno,t.deptno,t.ename
	from 
		emp e 
	join 
		(select 
			empno ,deptno,ename,mgr,date_format(t1.hiredate,'%Y%m%d') as tdate 
		from 
			emp t1) t 
	on
		e.empno  = t.mgr and t.tdate<date_format(e.hiredate,'%Y%m%d')) m 
on
	m.deptno = d.deptno 
order by 
empno asc;

    +-------+-------+------------+
    | empno | ename | dname      |
    +-------+-------+------------+
    |  7369 | SMITH | RESEARCH   |
    |  7499 | ALLEN | SALES      |
    |  7521 | WARD  | SALES      |
    |  7566 | JONES | RESEARCH   |
    |  7698 | BLAKE | SALES      |
    |  7782 | CLARK | ACCOUNTING |
    +-------+-------+------------+

16.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
select d.dname,t.* from dept d left join (
	select * from emp 
) t
on
d.deptno = t.deptno;
//通过连接emp的*查询,同时设置left部门表为主表,因为其没有员工的部门也要输出.
//然后条件就是t表的部门编号等于d表的部门编号,然后输出dname,和t的全部
+------------+-------+--------+-----------+------+------------+---------+---------+--------+
| dname      | EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+------------+-------+--------+-----------+------+------------+---------+---------+--------+
| ACCOUNTING |  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
| ACCOUNTING |  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
| ACCOUNTING |  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
| RESEARCH   |  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
| RESEARCH   |  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
| RESEARCH   |  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
| RESEARCH   |  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
| RESEARCH   |  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
| SALES      |  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
| SALES      |  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
| SALES      |  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
| SALES      |  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
| SALES      |  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
| SALES      |  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
| OPERATIONS |  NULL | NULL   | NULL      | NULL | NULL       |    NULL |    NULL |   NULL |
+------------+-------+--------+-----------+------+------------+---------+---------+--------+
17.列出至少有 5 个员工的所有部门
select deptno,count(*) num from emp group by deptno having num>=5;
//	
select d.dname,t.num from dept d join (select deptno,count(*) num from emp group by deptno having num>=5) t on
d.deptno = t.deptno;

    +----------+-----+
    | dname    | num |
    +----------+-----+
    | RESEARCH |   5 |
    | SALES    |   6 |
    +----------+-----+
18.列出薪金比"SMITH"多的所有员工信息.
select sal from emp where
ename='smith'; //先查出smith的薪资
select t.* from emp t join (select sal from emp where
ename='smith') e on
t.sal >e.sal; //然后表连接输出比smith的sal大的员工信息
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
19.列出所有"CLERK"(办事员)的姓名及其部门名称,部门的人数.
select e.ename,e.empno,e.deptno from emp e where job='clerk';
//先查出工作是clerk的姓名编号的部门编号
select t.ename,d.dname,m.num from dept d join (select e.ename,e.empno,e.deptno from emp e where job='clerk') t on
t.deptno = d.deptno
//然后连接部门表查出部门名称,条件是部门编号等于部门编号
join (select deptno,count(deptno) as num from emp  group by deptno) m 
on
m.deptno = t.deptno;
//然后再查出这个部门的人数,通过部门编号
    +--------+------------+-----+
    | ename  | dname      | num |
    +--------+------------+-----+
    | SMITH  | RESEARCH   |   5 |
    | ADAMS  | RESEARCH   |   5 |
    | JAMES  | SALES      |   6 |
    | MILLER | ACCOUNTING |   3 |
    +--------+------------+-----+
20、列出最低薪金大于 1500 的各种工作及从事此工作的全部雇员人数.
select e.job from  emp e group by job having min(sal)>1500;
//先查出最低薪资大于1500的工作是什么
select e2.job,count(e2.job) from emp e2 join (select e.job from  emp e group by job having min(sal)>1500) t on
t.job = e2.job
group by job;
//然后再查出这个工作有多少人,通过表连接,然后通过工作分组分组
    +-----------+---------------+
    | job       | count(e2.job) |
    +-----------+---------------+
    | ANALYST   |             2 |
    | MANAGER   |             3 |
    | PRESIDENT |             1 |
    +-----------+---------------+
21.列出在部门"SALES"<销售部>工作的员工的姓名,假定不知道销售部的部 门编号.
1.select ename,job from emp where deptno not in (10,20,40);
    +--------+----------+
    | ename  | job      |
    +--------+----------+
    | ALLEN  | SALESMAN |
    | WARD   | SALESMAN |
    | MARTIN | SALESMAN |
    | BLAKE  | MANAGER  |
    | TURNER | SALESMAN |
    | JAMES  | CLERK    |
    +--------+----------+
22.列出薪金高于公司平均薪金的所有员工,所在部门,上级领导,雇员的工资等 级.
select avg(sal) as avgsal from emp;
//先查询出公司的平均工资avgsal
select e.ename,e.sal,d.dname,e2.ename,s.grade from emp e  join (select avg(sal) as avgsal from emp) t 
on
e.sal > t.avgsal
join dept d
on
d.deptno = e.deptno
left join emp e2
on
e.mgr = e2.empno
join salgrade s
on
e.sal between s.losal and s.hisal;
	//然后再跟emp连接,查出大于avgsal的名字,工资,等,
	再跟部门表连接。查出部门名称,
	再跟emp连接一下,然后设置左为主表,查出前面的符合要求的员工的上级领导的编号。
	再与工资表连接,查出前面工资的等级,结束
    +-------+---------+------------+-------+-------+
    | ename | sal     | dname      | ename | grade |
    +-------+---------+------------+-------+-------+
    | JONES | 2975.00 | RESEARCH   | KING  |     4 |
    | BLAKE | 2850.00 | SALES      | KING  |     4 |
    | CLARK | 2450.00 | ACCOUNTING | KING  |     4 |
    | SCOTT | 3000.00 | RESEARCH   | JONES |     4 |
    | KING  | 5000.00 | ACCOUNTING | NULL  |     5 |
    | FORD  | 3000.00 | RESEARCH   | JONES |     4 |
    +-------+---------+------------+-------+-------+
23.列出与"SCOTT"从事相同工作的所有员工及部门名称.
select e.job from emp e where ename='scott';
//先进行job的查找,条件是name等于scott
select e2.ename,e2.deptno,d.dname from emp e2 join (select e.job from emp e where ename='scott') t
on
e2.job = t.job
join dept d
on
d.deptno = e2.deptno
where e2.ename  <> 'scott';
//然后再进行查找job的scott这个员工的job的,并且name不是scott的,然后再连接部门表,进行查找部门名称.
    +-------+--------+----------+
    | ename | deptno | dname    |
    +-------+--------+----------+
    | FORD  |     20 | RESEARCH |
    +-------+--------+----------+
24、列出薪金等于部门 30 中员工的薪金的其他员工的姓名和薪金.
select e2.sal,e2.ename from emp e2 join (select e.sal from emp e where deptno=30) s on e2.sal=s.sal where deptno!=30 ;
//先查找部门等于三十的员工薪资 t,
然后在进行表的连接,查找薪资等于t的员工信息,并且条件是部门不等于30
结果为空!
---------------------------------------------------
25、列出薪金高于在部门 30 工作的所有员工的薪金的员工姓名和薪金.部门名 称.
select distinct e2.sal,e2.ename,d.dname from emp e2 join (select max(e.sal) sal from emp e where deptno=30) s on e2.sal>s.sal   
join dept d on e2.deptno=d.deptno
where e2.deptno!=30 ;
//大于,所以是>,并且连接部门,然后连接部门表查询部门名称
    +---------+-------+------------+
    | sal     | ename | dname      |
    +---------+-------+------------+
    | 2975.00 | JONES | RESEARCH   |
    | 3000.00 | SCOTT | RESEARCH   |
    | 5000.00 | KING  | ACCOUNTING |
    | 3000.00 | FORD  | RESEARCH   |
    +---------+-------+------------+
26、列出在每个部门工作的员工数量,平均工资和平均服务期限.
select count(*) num,avg(sal) as avgsal,ceil(avg(date_format(now(),'%Y')-date_format(hiredate,'%Y'))) avgyear from emp group by deptno;
//查询数量 平均工资 平均服务年限,通过ceil方法进行向上取整
+-----+-------------+---------+
| num | avgsal      | avgyear |
+-----+-------------+---------+
|   3 | 2916.666667 |      41 |
|   5 | 2175.000000 |      39 |
|   6 | 1566.666667 |      41 |
+-----+-------------+---------+
27、列出所有员工的姓名、部门名称和工资
select  e.ename,d.dname,sal from emp e join 
dept d 
on 
e.deptno= d.deptno;
//两个表的连接,比较简单
    +--------+------------+---------+
    | ename  | dname      | sal     |
    +--------+------------+---------+
    | CLARK  | ACCOUNTING | 2450.00 |
    | KING   | ACCOUNTING | 5000.00 |
    | MILLER | ACCOUNTING | 1300.00 |
    | SMITH  | RESEARCH   |  800.00 |
    | JONES  | RESEARCH   | 2975.00 |
    | SCOTT  | RESEARCH   | 3000.00 |
    | ADAMS  | RESEARCH   | 1100.00 |
    | FORD   | RESEARCH   | 3000.00 |
    | ALLEN  | SALES      | 1600.00 |
    | WARD   | SALES      | 1250.00 |
    | MARTIN | SALES      | 1250.00 |
    | BLAKE  | SALES      | 2850.00 |
    | TURNER | SALES      | 1500.00 |
    | JAMES  | SALES      |  950.00 |
    +--------+------------+---------+
28.列出所有部门的详细信息和人数
select d.*,count(e.deptno) '人数' from dept d left join emp e
on
e.deptno = d.deptno
group by e.deptno;
//这里选择左边的表为主表,因为40编号的部门没有人员,若不为主表则匹配deptno不成功,则会被筛掉,所以设为主表.
//2.然后查人数时,要以e.deptno来查,因为e.deptno在40编号的部门为0,才能输出正确.
//若以d.deptno来查count时,40部门会查出1,主表的40部门没有匹配也会被当作一个成功的值
+--------+------------+----------+------+
| DEPTNO | DNAME      | LOC      | 人数  |
+--------+------------+----------+------+
|     40 | OPERATIONS | BOSTON   |    0 |
|     10 | ACCOUNTING | NEW YORK |    3 |
|     20 | RESEARCH   | DALLAS   |    5 |
|     30 | SALES      | CHICAGO  |    6 |
+--------+------------+----------+------+
29.列出各种工作的最低工资及从事此工作的雇员姓名
select e.job,min(sal) minsal from emp e group by job;
//先查找出工作和最低工资是多少
select t.* from emp t join (select e.job,min(sal) minsal from emp e group by job) m 
on
m.job = t.job and  m.minsal =t.sal;
//然后再进行表连接,查找所有.t表与m临时表进行连接,条件是工作相匹配并且工资相匹配
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
+-------+--------+-----------+------+------------+---------+---------+--------+
30、列出各个部门的 MANAGER(领导)的最低薪金
select 
	e.deptno,min(e.sal) 
from 
	emp e 
where 
	e.job ='manager'  
group by 
	deptno;
	//通过emp表的查询,然后条件是工作是manager的,并且再通过deptno部门编号分组,就可以查到部门的最低manager的薪资了.
    +--------+------------+
    | deptno | min(e.sal) |
    +--------+------------+
    |     10 |    2450.00 |
    |     20 |    2975.00 |
    |     30 |    2850.00 |
    +--------+------------+
31、列出所有员工的年工资,按年薪从低到高排序
select 
	ename,(sal*12+ifnull(comm,0)) yearsal 
from 
	emp 
order by 
	yearsal asc;
//年薪,通过sal*12加上comm补助,若为空,则设置为0
+--------+----------+
| ename  | yearsal  |
+--------+----------+
| SMITH  |  9600.00 |
| JAMES  | 11400.00 |
| ADAMS  | 13200.00 |
| WARD   | 15500.00 |
| MILLER | 15600.00 |
| MARTIN | 16400.00 |
| TURNER | 18000.00 |
| ALLEN  | 19500.00 |
| CLARK  | 29400.00 |
| BLAKE  | 34200.00 |
| JONES  | 35700.00 |
| FORD   | 36000.00 |
| SCOTT  | 36000.00 |
| KING   | 60000.00 |
+--------+----------+
32、求出员工领导的薪水超过 3000 的员工名称与领导名称
select 
	e.ename,e.mgr 
from emp;
//先查询emp中mgr与name

	select 
t.ename,m.ename 
	from emp t 
join 
	(select e.ename,e.mgr from emp e) m
on
	m.mgr = t.empno
where
	t.sal>3000;
//再通过表连接,进行查询,条件是mgr等于empno,则输出这个empno的name
    +-------+-------+
    | ename | ename |
    +-------+-------+
    | KING  | JONES |
    | KING  | BLAKE |
    | KING  | CLARK |
    +-------+-------+
33、求出部门名称中,带’S’字符的部门员工的工资合计、部门人数.
select d.deptno,d.dname from dept d where d.dname like '%s%';
//首先查出带s的部门,为3个
+--------+------------+
| deptno | dname      |
+--------+------------+
|     20 | RESEARCH   |
|     30 | SALES      |
|     40 | OPERATIONS |
+--------+------------+
select  t.dname,sum(e.sal),count(e.deptno) from emp e right join (select d.deptno,d.dname from dept d where d.dname like '%s%') t
on
e.deptno = t.deptno
group by t.deptno;
//然后再通过表的连接,进行查询工资的合计和人数,条件为部门编号等于部门编号,通过部门编号分组
+------------+------------+-----------------+
| dname      | sum(e.sal) | count(e.deptno) |
+------------+------------+-----------------+
| RESEARCH   |   10875.00 |               5 |
| SALES      |    9400.00 |               6 |
| OPERATIONS |       NULL |               0 |
+------------+------------+-----------------+
34、给任职日期超过 30 年的员工加薪 10%.
select date_format(now(),'%Y')-date_format(e.hiredate,'%Y') isPth from emp e;
//查出大于三十的,检查有没有,结果为有,(并且全部)
+-------+
| isPth |
+-------+
|    42 |
|    41 |
|    41 |
|    41 |
|    41 |
|    41 |
|    41 |
|    35 |
|    41 |
|    41 |
|    35 |
|    41 |
|    41 |
|    40 |
+-------+

update 
	emp 
set 
	sal=1.1*sal 
where 
	(date_format(now(),'%Y')-date_format(hiredate,'%Y')) >30;
//更新emp表中sal= 1.1sal,并且条件为现在时间减去入职日期是否大于30,用到了date_fromat转换为字符串.
//更新之前的表
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
//更新之后的表
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  880.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1760.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1375.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 3272.50 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1375.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 3135.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2695.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3300.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5500.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1650.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1210.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 | 1045.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3300.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1430.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+

五、对表结构的修改

什么是对表结构的修改?alter DDL语句
DDL包括create,drop,alter
	添加一个字段,删除一个字段,修改一个字段!!
	第一:
		在实际的开发者,不经常需要对修改表结构进行修改
	第二:
		如果需要对表结构进行修改,可以借助工具.

六、约束(重要!!! *****************)

6.1基本概念
6.1.1创建表加入约束
	什么是约束呢? constraint
	在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中的数据玩完整性 有效性!
	约束的作用:保证表中的数据有效!
6.1.2约束包括那些?
	非空约束: not null
	唯一性约束: unique
	主键约束: primary key(简称PK)
	外键约束: foreign key(简称FK)
	检查约束: check (mysql不支持,oracle支持)
	
	主要学习前四个 not null unique primary key foreign key
	3.2.1 非空约束:not null,约束的字段不能为空
	drop table if exists t_vip;
	create table t_vip(
		id int,
		name varchar(255) not null,
	);
	insert into t_vip values(1,'zhangsan');
	insert into t_vip values(2,'lisi');
	insert into t_vip values(3)
xxxx.sql被称为sql脚本文件,在执行sql脚本时,该文件中的所有娥sql语句全部都会被执行,
批量的执行sql语句,可以使用sql脚本文件
在mysql当中可以使用source 跟上绝对路径
来添加一个表或数据库
 source D:\APPDATA1\t_vip.sql
 	
mysql> select * from t_vip;
    +------+----------+
    | id   | name     |
    +------+----------+
    |    1 | zhangsan |
    |    2 | lisi     |
    +------+----------+
6.1.3进行非空测试
 	insert into t_vip(id) values(4);
 	报错:  Field 'name' doesn't have a default value //name字段没有默认值,由于加了非空关键字
6.2唯一性约束: unique
6.2.1约束的字段不能重复,但可以为null,null不是重复
drop table if exists t_vip;
create table t_vip(
	id int,
	name varchar(255) unique,
	email varchar(255)
);
insert into t_vip(id,name,email) values (1,'lisi','123123@qq.com');
insert into t_vip values (2,'shangsan','456465@qq.com');
insert into t_vip(id,name,email) values(3,'lisi','789789@qq.com');
//使用source导入sql脚本文件
报错:ERROR 1062 (23000): Duplicate entry 'lisi' for key 'name' //由于3和1的name重复,设置了name唯一性.
name虽然被唯一性约束了,但都可以为null,null为空,不存在重复

6.2.2新需求:name和email两个字段联合起来具有唯一性!!
	drop table if exists t_vip;
	create table t_vip(
		id int,
		name varchar(255) ,
		email varchar(255),
		unique(name,email)
	);
	//name和email两个字段联合起来唯一!!
	insert into t_vip(id,name,email) values(1,'zhangsan','123@qq.com');
	insert into t_vip(id,name,email) values(1,'zhangsan','123@sina.com');
	//成功插入!
 select * from t_vip;
+------+----------+--------------+
| id   | name     | email        |
+------+----------+--------------+
|    1 | zhangsan | 123@qq.com   |
|    1 | zhangsan | 123@sina.com |
+------+----------+--------------+

注意:约束直接添加在列后面的,叫做列级约束,
6.2.3约束没有添加在列的后面,这种约束被称为表级约束!(在多个字段联合起来添加某一个约束的时候)
 	not null 和 unique 的联合使用:
 	drop table if exists t_vip;
 	create table t_vip(
 		id int,
 		name varchar(255) not null unique
 	);
 	//查看表的结构
 	+-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int(11)      | YES  |     | NULL    |       |
    | name  | varchar(255) | NO   | PRI | NULL    |       |
    +-------+--------------+------+-----+---------+-------+
    //当not null 和unique联合使用时,自动将其这一个字段当成主键(oracle中不是这样的!)
    
6.3主键约束(primary key 简称PK)
主键的相关术语:
	主键字段:该字段添加了主键约束,这样的字段被称为主键字段.
	主键值:主键字段中的每一份值,叫做主键值
6.3.1什么是主键?作用?
	主键是每一行记录的唯一标识.
	主键是每一行记录的身份证号!
	注意:每一张表都应有主键,没有主键表无效!
	主键的特征:not null+ unique(不能为空,唯一性)
6.3.2添加一个主键约束:
		drop table if exists t_vip;
		create table t_vip(
			//一个字段做主键,叫做单一主键
			id int primary key,//也可以表级约束
			name varchar(255)
		);
		insert into t_vip(id,name) values(1,'lisi');
		insert into t_vip(id,name) values(2,'lisi');
		select * from t_vip;
		+----+------+
        | id | name |
        +----+------+
        |  1 | lisi |
        |  2 | lisi |
        +----+------+
        //直插入一个name呢?
        insert into t_vip(name) values('zhangsan');
        //报错:
        Field 'id' doesn't have a default value
6.3.3多个字段联合主键:(叫做复合主键)
	drop table if exists t_vip;
		create table t_vip(
			//一个字段做主键,叫做单一主键
			id int ,//也可以表级约束
			name varchar(255),
			primary key(id,name) //复合主键
		);
		//id和name联合起来做主键,当两个完全相同时,才会插入失败!
		注意:再开发中,不建议使用复合主键!使用单一主键即可!!!
6.3.4一个表中可以添加两个主键嘛?
	drop table if exists t_vip;
		create table t_vip(
			id int primary key,
			name varchar(255) primary key
		);
		//报错:Multiple primary key defined,主键重复定义!,主键一个表中只能有一个.
6.3.5主键类型建议使用 int bigint char等类型.不建议使用varchar,一般主键都为定长!
6.3.6主键除了分为单一主键和复合主键还分为 自由主键和业务主键
尽量使用自由主键,由于业务主键会根据业务的改变而影响主键.
	6.3.6.1在mysql中,有一种机制,可以帮助我们自动维护一个主键值/
	drop table if exists t_vip;
		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('zhangsan');
		insert into t_vip(idname) values('zhangsan');
		insert into t_vip(name) values('zhangsan');
		insert into t_vip(name) values('zhangsan');
		insert into t_vip(name) values('zhangsan');
		select * from t_vip;
		//自增,不用再给其主键值,如果你给了某一个字段了主键值,那么再自增时,就会按照你给定的上一次的主键值进行自增
		+----+----------+
        | id | name     |
        +----+----------+
        |  1 | zhangsan |
        |  2 | zhangsan |
        |  3 | zhangsan |
        |  4 | zhangsan |
        |  5 | zhangsan |
        |  6 | zhangsan |
        +----+----------+
6.4外键约束(foreign key 简称FK) 非常重要!!!
外键约束涉及到的相关术语:
	外键约束:一种约束
	外键字段:如果一个字段里添加了外键约束,则这个字段被称为外键字段
	外键值:外键字段上的所有值,都被称为外键值
	
业务背景:
	请设计数据库表,来描述班级和学生信息?
		第一种方案:班级和学生设计在一张表中.
		t_student
		no(pk)   name   classno   calssname
--------------------------------------------------------- 
		1        jack      100     高三一班
		2         lisi     100     高三一班
		3         zhangsan 101     高三2班
		4         wangliu  101     高三2班
		5         beixi    101     高三2班
		...
		这种设计的缺点?
			数据冗余,空间造成浪费,这种设计是比较失败的
	第二种方案,班级一张表,学生一张表?
	t_student 学生表
	no(pk)   name     cno(FK引用t_class这张表的calssno)   
----------------------------------
		1         jack     100 
		2         lisi     100 
		3         zhangsan 101 
		4         wangliu  101 
		5         beixi    101 
	//当cno没有任何约束的时候,可能会导致数据无效,出现了班级表cno之外的值,可以加一个外键约束,那么:cno字段就是外键字段,cno字段中的每一个值都是外键值
	t_class 班级表
		cno(pk)   classname
----------------------------
		100         高三一班    
		101         高三二班  
      注意:t_class是父表,t_student是子表
      删除表的顺序,先删子,再删父.
      创建表的顺序,先创父,再创子.
      插入数据的顺序,先插入父,再插入子.
编写t_student和t-class表
drop table if exists t_student;
drop table if exists t_class;
create table t_class(
	cno 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(cno)
);
//外键是cno,然后参考或继承于t_class表中的cno
insert into t_class(cno,classname) values(100,'高三一班');
insert into t_class(cno,classname) values(101,'高三二班');

insert into t_student(name,calssno) values('jack','100');
insert into t_student(no,name,cno) values('lisi','100');
insert into t_student(no,name,cno) values('zhangsan','101');
insert into t_student(no,name,cno) values('wangliu','101');
insert into t_student(no,name,cno) values('beixi','101');
select * from t_class;
select * from t_student;

思考?子表中的外键引用父表中的某个字段,被引用的这个字段必须是主键嘛?
    被引用的不一定是主键,但一定是唯一的,unique约束.
测试:外键(子表)可以为空嘛?
    可以为null,

七.存储引擎(了解内容)

7.1什么是存储引擎?作用?
	存储引擎是mysql中特有的术语,存储引擎是一个表存储引擎或组织数据的方式.不同的存储引擎,表存储数据的方式不同.
7.2怎么给表添加/指定'存储引擎呢?
	执行下面命令:
	show create table t_student;
	
CREATE TABLE `t_student` (
  `no` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `cno` int(11) DEFAULT NULL,
  PRIMARY KEY (`no`),
  KEY `cno` (`cno`),
  CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `t_class` (`cno`)
) 
ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 
在建表的时候可以再最后,")"的后面指定引擎的格式
ENGINE来指定存储引擎.
CHARSET 来指定这张表的字符编码方式.

结论:
	mysql默认的存储引擎是:InnoDB
	mysql默认的字符编码方式是:utf8
==>	若你在建表时指定字符集为gdk,就可以在命令终端写入中文字符串.
	安装mysql时指定的字符集
7.3怎么查看mysql支持哪些存储引擎呢?
命令 show engines \G;
mysql支持九大存储引擎,版本不同支持的情况不同.
7.4各个版本的存储引擎的简单分析
	MyISAM:
		它管理的存储引擎具有一下几个特征:
			使用三个文件表示每个表:
				格式文件-存储表结构的定义(mytable.frm)
				数据文件-存储表行的内容(mytable.mMYD)
				索引文件-存储表上索引(mytable.MYT):索引就相当于一本书的目录,大大的缩小了查找的范围.
		可以转换为压缩\只读来节省空间
		提示:
			对于一张表来说,只要是主键,或炸加有unique约束的字段会自动创建索引.
		MyISAM存储引擎的特点:
			可被转换为压缩\只读表来节省空间
			MyISAM存储引擎的优势所在!
			不支持事务,安全性低
	InnoDB:
		mysql的默认存储引擎,同时也是重量级的存储引擎.
        InnoDB支持事务,支持数据库崩溃后自动恢复机制
        最主要的特点,就是非常安全
        每个InnoDB 表在数据库目录中以.frm格式文件表示
        InnoDB 表空间 tablespace 被用于存储表的内容(表空间是一个逻辑名称,表空间存储数据+索引)
        提供一组用来记录事务性活动的日志性文件
        支持事务
        支持外键以引用的完整性,包括级联删除和更新
        InnoDB最大的特点就是支持事务:
        	以保证数据的安全.效率不高,并且不能压缩,不能转换只读.
	MEMORY存储引擎?
		在数据库目录内,每个表均以.frm格式的文件表示
		表数据及索引被存储在内存中(目的就是快)
		表级锁机制
		不能包含text和blob字段
		以前也叫做heap引擎
		优点:
			查询效率最高.不需要和硬盘交互
		缺点:
			不安全,关机数据会因为内存的消失而消失.

八、事务(必须掌握************** 必须精通**************)

8.1什么是事务?
	一个事务就是一个完整的业务逻辑.
	是一个最小的工作单元,不可以再分.它是一个操作序列,要么都执行,要么都不执行.在关系数据库中,一个事务可以是一个SQL语句,也可以是一组SQL语句,或整个程序.在每个事务结束时,都能保持数据的一致性.
	8.1.2 存在事务的原因是什么?
		最根本的原因就是保证数据的一致性.一个完整的业务,事务能保证它要不都成功,要么都不成功! 
		举个例子说,银行转账业务,有甲方和乙方,在转账的过程中,需要在甲账户在数据库记录的数据中减10000,在乙方中加10000,执行甲减一万语句成功之后,在执行乙的时候,出错了,如果没有事务的保证,那么数据就出错了.乙没有收到,而甲少了一万.所以需要要么都执行,要么都不执行.
8.2只有DML语句才会有事务这一说.
insert delete update
涉及对数据的增删改,才会考虑安全问题.
数据安全第一位!!
8.3假设所有的业务,只要一条DML语句就能完成,还有必要存在事务机制嘛?
	没有必要存在事务了!! 因为一条语句要么成功,要么失败,所以也就没有事务存在的必要了.
8.4事务是怎么做到多个DML语句同时成功,同时失败的?
	innoDB存储引擎:提供一组用来记录事务性活动的日志文件
	模拟事务:
		事务开启了..
		insert...
		insert...
		update...
		delete...  
        事务结束了!
        在事务执行的过程中,每一条DML的操作都会记录到"事务性活动的文件"中.
        在事务的执行过程中,我们可以提交事务,也可以回滚事务.
      		提交事务?
            	清空事务性活动的日志性文件,将数据全部彻底持久化到数据库表中.
            	添加事务标志着事务的结束,并且是全部成功的结束!
            回滚事务?
            	将之前的所有的DML操作全部撤销,并且清空事务性活动的日志文件,回滚事务标志着事务的结束,并且是一种全部失败的结束.
8.5怎么提交事务?怎么回滚事务?
提交事务:commit;
事务回滚: rollback;
事务对应的英语单词: transaction.

在mysql当中默认的事务行为是怎样的?
mysql默认情况下是支持自动提交,每执行一条DML语句,自动提交一次!
==>rollback则可以回到上一次的提交点.
怎么将默认的提交行为取消掉呢?
	在你开始DML语句之前写入 start tansaction;//表示事务开始
	drop table if exists dept_back;
	create table dept_back(
		id int primary key,
		name varchar(255)
	);
	start transaction;
	insert into dept_back(id,name) values(1,'jack');
	insert into dept_back(id,name) values(2,'jack');
	insert into dept_back(id,name) values(3,'jack');
	insert into dept_back(id,name) values(4,'jack');
	insert into dept_back(id,name) values(5,'jack');
	commit;//提交之后,事务就结束了,再执行新的DML语句就会默认自动提交了.所以如果测试,还需要再重新开启事务开启..
	start transaction;
	insert into dept_back(id,name) values(6,'jack');
	rollback;
	//查询到的结果
	+----+------+
    | id | name |
    +----+------+
    |  1 | jack |
    |  2 | jack |
    |  3 | jack |
    |  4 | jack |
    |  5 | jack |
    +----+------+
	 //事务回滚
	 select * from dept_back;
	 //查询表数据,
	 Empty set (0.00 sec) //空表,说明回滚到上次提交的地点.
	 这种默认提交行为是不符合我们的开发习惯的,我们开发是需要等全部语句执行完成之后,才会提交!
8.6事务的四个特性:
	A:原子性
		说明事务是不可再分的工作单元
	C:一致性
		说明同一个事务当中,所有操作必须同时成功或同时失败
	I:隔离性
		事务之间具有一定的隔离.
		例:A事务在操作一张表的时候,另一个事务B也操作这张表会怎样?
	D:持久性
		事务最终结束的一个保障,事务提交:相当于没有保存在硬盘上的数据保存在硬盘上.

8.7事务的隔离性!!!

事务的隔离是有隔离级别的,事务与事务的隔离的级别有四个?
	四个级别?
		1.读未提交:read uncommitted(最低级别)
			1.1事务A可以读取事务B未提交的数据.
			1.2这种隔离级别存在的问题就是:
				脏读现象!(Dirty Read)
				我们称读到了脏数据!!!(对方没有提交的数据我么称为脏数据)
			这种隔离级别一般都是理论上的.大多数都是二档起步!
		2.读已提交:read committed
			2.1事务A只能读取到事务B提交之后的数据.
			2.2这种隔离解决了脏读的现象.
			2.3这种隔离级别存在的问题=>是不可重复读取数据!!
				2.3.1什么是不可重复读呢?
					在事务B提交一次后,事务A读取了一条数据,然后事务B再提交一次后,事务A读到来了2条数据....即读到的数据不一样,1不等于2=>所以称为不可重复读取!
			2.4这种隔离级别是比较真实的数据,每一次读到的数据是绝对的真实!oracle数据库默认的隔离级别是:read committed
		3.可重复读:repeatable read
			3.1可重复读取:
				事务A开启时,表当时的数据就是y读取的数据,不论事务B对表进行什么样的操作(增删改 提交事务等..).只要事务A没有提交,则每一次事务A在表读取到的数据都是一样的,这叫做可重复读!!
			3.2解决了不可重复读问题!!!
			3.3存在什么问题?
					幻影,每一次读到的数据都是幻想,不够真实!!!
		4.序列化/串行化:serializable(最高的隔离级别)
			最高级别,效率最低,解决了所有问题,
			这种隔离级别表示任务排队,不能并发!
			synchronized,线程同步(事务同步)
			每一次读取到的数据都是最真实的,但效率最低的!

8.8隔离级别的一些命令(查看,设置…)

8.8.1 查看:
select @@tx_isolation;
//mysql8.0是 select @@transaction_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+//可重复读!!
8.8.2设置隔离级别:
	set global transaction isolation level read uncommitted;

9.索引

9.1什么是索引?
	索引是数据库表的字段上添加的,是为了提高查询效率存在一种机制.
	一张表的一个字段可以添加一个索引,当前,多个字段联合起来也可以添加索引.
	索引相当于目录,为了缩小扫描范围而存在的一种机制.
	比如对于字典来说,一页一页挨着找,任务量非常的大,如果通过目录进行锁定在一个范围,那么查找起来会非常快的.效率很高
	select * from t_user where name='jack';
	这条sql语句会去name字段上扫描.因为查询条件是name='jack'
	如果name字段上"没有"添加索引,那么将会全扫描.将name上的值全一一对比,效率很低.
	msyql的查询方式有两种方式:
		全表扫描
		根据索引检索.
		注意:目录也需要排序,才会有区间,才会有区间查找.这样方便查找,效率更高.
		在mysql数据库当中索引也是需要排序的(a.b.c.d...).并且这个索引的排序和TreeSet(TreeMap)数据结构相同,TreeSet底层是一个自平衡的二叉树.
		mysql中的索引是一个B-Tree数据结构.遵循左小右大原则存放,采用中序遍历方式遍历取数据.
9.1索引的实现原理
现在有这么一张表
t_user
id(PK)    name    (物理地址)
----------------------------
100       zqk        0x123
101       jack       0x124
120       tom        0x125
130       lisi       0x126
99        wangwu     0x127
88        zhaoliu    0x128
55        beixi      0x129

sql查询语句:
	select * from t_user where id=101
通过id为101这个条件查找,又因为主键自动设置索引,并且存储起来,所以在查找101时就是通过索引查找,更加高效,其内部使用了B-Tree二分查找.
 提示:在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MyISAM中,索引存储在.MYI文件中,在InnoDB中,索引存储在一个逻辑名称为tablespace当中,在MEMORY引擎当中,索引在内存当中,索引在mysql当中都是以一个树的形式存在的.(自平衡二叉树:B-Tree)
	画图演示如下:
9.1.2 主键上,unique字段上都会自动添加索引的.	
	什么条件下,会考虑给字段添加索引呢?
		1.数据量庞大(测试!)
		2.某个字段经常出现在where后面,以条件的形式存在,总是被扫描.
		3.该字段很少使用DML语句(delete,update,insert)操作.
		因为DML后,索引需要重新排序.
		
		建议不要随便添加索引,因为索引也是需要维护的.太多的索引反而减低系统的性能.
		建议通过主键查询 unique约束的字段进行查询,效率反而是比较高的.

9.2索引的创建和删除
创建:
	create index emp_ename_index on emp(ename);
	给emp的ename创建索引,起名为emp_ename_index
删除索引:
	drop index emp_ename_index on emp;
	将emp表上的emp_ename_index索引删除.
怎么查看一个sql语句是否使用了索引?(explain关键字)
explain select * from emp where ename='king'+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
//可以发现,类型为all,全扫描,搜索了14行,没有索引.
9.2.2我们手动给它加上索引之后,在进行查询
create index emp_ename_index on emp(ename);
explain select * from emp where ename='king';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | emp   | ref  | emp_ename_index | emp_ename_index | 33      | const |    1 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
//可以看到它只搜索了一条就查询出来了..
9.3索引的失效
1.模糊查询%开始.
explain select * from emp where ename like '%t';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+ //14条匹配次数
ename即使添加了索引,也不会走索引,因为%开始,不确定前面的数据,所以每一项数据都得查找.
	::尽量避免模糊查询以"%"开始.
2.使用or得时候会失效.
	如果使用or那么要求or两边得条件都要有索引,才会走索引,如果其中一边没有没有索引,那么另一个字段的索引不会实现,所以在开发中不建议使用or得原因.
	可以使用union连接结果进行查询!!
3.使用复合索引的时候,没有使用左侧列查找,索引失效!
	3.1什么是复合索引?
		两个字段,或者更多的字段联合起来添加一个索引,叫做复合索引.
		create index emp_job_sal_index on emp(job,sal);
		explain select * from emp where job='manager';+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys     | key               | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | emp   | ref  | emp_job_sal_index | emp_job_sal_index | 30      | const |    3 | Using where |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
		explain select * from emp where sal=800; //查询时使用了左侧没有使用右侧,索引成功
		+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+//查询中使用右侧,没有使用左侧的job,索引失效.
	最左原则!!!
4.在where当中索引列(这个字段)参加了数学运算,索引失效!
	create index emp_sal on emp(sal);
	explain select * from emp where sal+1 >800;
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
//索引失效,查询次数为全表.
5.在where当中索引使用了单行函数
create index emp_ename on emp(ename);
	explain select * from emp where lower(ename)='smith';
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+//索引失效,查询次数为全部.
9.4总结
索引时各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引.
	索引在数据库当中分了很多类?
		单一索引:一个字段上添加索引.
		复合索引:连个字段或者更多的字段上添加索引.
		主键索引:主键上添加索引
		唯一性索引:具有unique约束的字段上添加索引.
		....
		注意:唯一性比较若的字段上添加索引用处不大.

10.视图

10.1什么是视图?
	view:站在不同的角度去看待同一份数据.
10.2怎么创建视图对象? 怎么删除视图对象?
	create view emp_view as select * from emp;//视图对应的后面只能是DQL语句
	复制一张表:
		create table dept2 as select * from dept;
		create view dept2_view as select * from dept2;
10.3删除视图:
	drop view dept2_view;
	注意:只有DQL语句才能以view的形式创建.(select)
10.4我们用视图做什么?
	对视图进行增删改查,会影响到原表数据.
10.5视图对象在实际开发中到底有什么用?
	简化sql语句.视图可以进行简化sql语句来创建一个视图表示,既可以进行增删改查,又可以达到简化的目的.
	例:
		create view 
			emp_dept_view 
		as
            select 
                e.ename,e.sal,d.dname 
            from 
                emp e
            join 
                dept d
            on
            d.deptno = e.deptno;
            //这样,一个emp_dept_view视图就代替了下面的sql语句,如果一条sql语句非常复杂(一条一张A4纸),那么视图是非常简化sql语句的!!
            当你需要修改的时候,只需要修改视图所映射的SQL语句!
       视图也是存储在硬盘上的,不会消失。
       优点:
       	方便,简化开发,利于维护
       	

11.DBA命令

11.1掌握数据的导入与导出(数据的备份)
	1.数据导出:mysqldump bjpowernode>D:\bjpowernode.sql -uroot -proot
	导出到d盘.
	1.2导出指定的表:
		mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot -proot
	2.导入,在数据库中,进行导入:
		source 文件绝对路径
		例:
			drop database bjpowernode;
			create database bjpowernode;
			use bjpowernode;
			source D:\bjpowernode.sql

12.数据库设计三范式

12.1什么是数据库设计范式呢?
	数据库表的额设计依据.教你怎么进行设计
		第一范式:要求任何一张表要求有主键,没一个字段不可再分
		第二范式:建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖
		第三范式:建立在第二范式的基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖.
		注意:三范式经常问到在面试中!!!
12.2 第一范式:
	必须有主键,并且每一个字段都不可再分>>
	例:下面有一张t_student表,请回答它符合第一范式嘛?
	sno(pk)    name     email        phone
	----------------------------------------
	101        jack    123@139.com   1454546
	102        tom     45@139.com    465789
	103        beixi   789@139.com   123465
	结果是符合的!!
12.3 第二范式:建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖	
	下面有个学生和老师的关系表:(多对多的关系)
		sno  +  tno(pk)   sname   tname
		-------------------------------
		1001     001      张三      王老师
		1002     002      李四      赵老师
		1003     001      王五      王老师
		1001     002      张三      赵老师
学生编号和老师编号联合起来做主键,复合主键(pk:sno+tno)
以上的表符合了第一范式,但是不符合第二范式.因为例如第一条记录张三对主键产生了部份依赖(只依赖1001),王老师也是(只依赖101)
	产生部分依赖有什么特点呢?
		数据冗余. 空间浪费 (重复...)
      为了满足第二范式,可以这样设计表:
      	使用三张表来表示多对多的关系;
      		学生表:
      		sno(pk)    sname
      		-------------------
      		1001        张三
      		1002        李四
      		1003        王五
      		教师表:
      		tno(pk)    tname
      		-----------------------
      		101         王老师
      		102         赵老师
      		关系表:
      		id(pk)     学生编号(fk)    教师编号(fk)
      		----------------------------------------
      		1            1001             001
      		2            1002             002
      		3            1003             001
      		4            1001             002
      		
 口诀:
     多对多怎么设计?
       多对多三张表,关系表两个外键.!!!!!!!
       
12.4第三范式:
	第三范式建立在第二范式的基础之上,
	要求所有的非主键字段必须直接依赖主键,不要产生传递依赖.
	下面有这个表
	sno(pk)    sname   classno   classname
	--------------------------------------------
	1001        lisi      01       一班
	1002        jack      02       二班
	1003        zhaoliu   03       三班
	1004        bak       03       三班
	
	班级-学生表,一个班级有多个学生,明显的一对多的关系.
	满足第一范式和第二范式,因为原子不可再分,有主键,二:非主键全部依赖主键,没有产生部分依赖(只有一个主键,并且sname,classno(班级可以依赖学号==)直接依赖,classname传递依赖都是全部依赖)
	但不满足第三范式
		产生了传递依赖=>一班通过班级编号依赖主键
	那么怎么设计一对多呢?
    一对多拆成两张表:
    	学生表:
    	sno(pk)      sname  classno(fk)  fk=>外键
    	---------------------------------
    	1001     lisi         01
    	1002     jack         02
    	1003     zhaoliu      03
    	1004     bak          03
    	班级表:
    	classno(pk)   classname
    	----------------------
    	01          一班
    	02          二班
    	03          三班
一对多:两张表,多的表加外键!

13总结数据库表的设计

多对多三张表,关系表两个外键.!!!!!!!
一对多:两张表,多的表加外键!
一对一:
	一对一放到一张表中不就行了嘛?为啥还要拆分?
	在实际的开发中,可能存在一张表字段太多,太庞大.这个时候要拆分表(数据庞大不好管理,拆分为两个或多张表).
	例:
		没有拆分之前:一张表
		t_user
		id   login_name   login_pwd   real_name   email  address ..
		------------------------------------------------------------
		1      zhangsan      123        张三       13@qq.com 
		2      lisi          123        李四       456@qq.com 
		
这样庞大的表可以拆分为两张表以便于管理:
	t_login 登录信息表
	id(pk)    login_name  login_pwd 
	------------------------------
	1      zhangsan       123
	2         lisi        123
	
	t_user 用户信息表
	id(pk)    real_name    email      address.....  login_id(fk+unique)
	--------------------------------------------------------------------
	100         张三        13@qq.com    					1
	200         李四        456@qq.com                    2
	口诀:一对一,外键唯一!!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值