MySQL笔记

一、常见的有哪些数据库管理系统:

Oracle 甲骨文(SUN太阳) --》Oracle吞并SUN公司
IBM公司 —》开发了eclipse
Oracle做数据库起家,Oracle收购了Mysql AB公司

常见的sql有:Oracle、Mysql、 DB2、 sybase、 “MS sqlServer 支持标准数据库管理系统”

IP地址是这台计算机在这个网络当中的唯一标识(身份号)
端口号是这台计算机上运行的每个软件都有一个端口,端口号就是每个正在运行的软件的唯一标识。 (端口号在同一台计算机上不能重复)

二、MySQL

1、sql、DB、DBMS分别是什么?他们的关系是?

DB:DataBase(数据库,数据库在硬盘上实际上是以文件的形式存在)
DBMS:DataBase Management System(数据库管理系统,常见的有:MySQL、Oracle、DB2、Sybase、Sqlserver)

SQL:结构化查询语言,是一门标准通用语言,标准的sql使用于所有的数据库产品。
SQL是高级语言,只要可以看懂英语单词,就可以读懂sql的意思
SQL语句在执行的时候实际上内部也会进行编译,然后执行sql语句(sql语句的编译由DBMS完成)

DBMS执行sql语句,通过执行sql语句,来操作DB中的数据
DBMS 执行sql, 最终操作的是DB

三、表(table)

行:就是数据
列:就是字段

1、什么是表table

表是数据库的基本组成单元,所有的数据都以表格的形式组织,目的是可读性强。
一张表包括行和列
行被称为数据/记录(data)
列被称为字段(column)

学号(int)  姓名(varchar) 年龄(int)
----------------------------------
110	      		 张三	  22
120              李四	  23
140              王五	  24

数据库中字符串叫:varchar

每一个字段应该有什么属性:
字段名、数据类型、相关的约束

2、学习MySQL主要是学习通用的sql语句,sql语句包括增删改查,那么sql语句如何分类?

  • DQL(数据查询语言):查询语句,凡是select语句都是DQL
  • DML(数据操作语言):insert、delete、update,对表中的数据进行增删改
  • DDL(数据定义语言):create、drop、alter,对表的结构进行增删改
  • TCL(事务控制语言):commit提交事务,rollback回滚事务。(TCL中的T是transaction事务的意思)
  • DCL(数据控制语言):grant授权,revoke撤销权限等。

3、导入数据

第一步:登录MySQL
Dos命令窗口:mysql -uroot -p123456
mysql -uroot -p
123456
第二步:查看有哪些数据库

show databases;(这个是mysql的命令,不属于sql语句)
+--------------------+
| Database           |
+--------------------+
| information_schema |
| 666                |
| mysql              |
| perfectcrm         |
| performance_schema |
| sqlexample         |
| sqlstudy           |
| sys                |
| test               |
+--------------------+

第三步:创建自己的数据库
create database study;(这个是mysql的命令,不属于sql语句)
第四步:使用自己创建的数据库
use study;(这个是mysql的命令,不属于sql语句)
第五步:查看当前使用的数据库中有哪些表
show tables;(这个是mysql的命令,不属于sql语句
第六步:初始化数据
source 加上文件绝对路径;(这个是mysql的命令,不属于sql语句

注意:数据初始化完成之后有三张表

4、sqlstudy.sql,这个文件以.sql结尾,称为“sql脚本”,什么是sql脚本?

以“.sql”结尾的文件,并且里面含有大量的sql语句,我们称这样的文件叫做sql脚本。

注意:直接使用source命令可以执行sql脚本
sql文件过大,可以使用source命令完成初始化。

5、删除数据库:drop database sqlstudy;

6、查看表结构

mysql> show tables;
+--------------------+
| Tables_in_sqlstudy |
+--------------------+
| dept               |	(部门表)
| emp                |	(员工表)
| salgrade           |	(员工等级表)
+--------------------+
mysql> desc dept;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| DEPTNO | int(2)      | NO   | PRI | NULL    |       |(部门编号)
| DNAME  | varchar(14) | YES  |     | NULL    |       |(部门名字)
| LOC    | varchar(13) | YES  |     | NULL    |       |(部门地理位置)
+--------+-------------+------+-----+---------+-------+
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| 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    |       |(员工部门编号)
+----------+-------------+------+-----+---------+-------+
mysql> desc salgrade;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| GRADE | int(11) | YES  |     | NULL    |       |(等级)
| LOSAL | int(11) | YES  |     | NULL    |       |(最低薪资)
| HISAL | int(11) | YES  |     | NULL    |       |(最高薪资)
+-------+---------+------+-----+---------+-------+

7、表格中的数据

select *from emp;(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 |
+-------+-------+-------+

8、常用命令:

mysql> select database();	// 查看当前使用的是哪个数据库(是命令,不是sql语句)
+------------+
| database() |
+------------+
| sqlstudy   |
+------------+

mysql> select version();	// 查看当前使用的数据库的版本号(是命令,不是sql语句)
+-----------+
| version() |
+-----------+
| 5.7.18    |
+-----------+

\c 命令结束一条语句

exit 命令退出MySQL

9、查看创建表的语句:

show create table 表名;

mysql> show create table emp;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                            |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| emp   | CREATE TABLE `emp` (
  `EMPNO` int(4) NOT NULL,
  `ENAME` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `JOB` varchar(9) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `MGR` int(4) DEFAULT NULL,
  `HIREDATE` date DEFAULT NULL,
  `SAL` double(7,2) DEFAULT NULL,
  `COMM` double(7,2) DEFAULT NULL,
  `DEPTNO` int(2) DEFAULT NULL,
  PRIMARY KEY (`EMPNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.03 sec)

10、简单的查询语句(sql语句)

语法格式:select 字段名1,字段名2,… from 表名;

提示:1、任何一条sql语句以“;”分号结尾。
2、sql语句不区分大小写。
3、sql语句的字符串以单引号括起来

// 查询员工姓名和职位

mysql> select ename,job from emp;
+--------+-----------+
| ename  | job       |
+--------+-----------+
| SMITH  | CLERK     |
| ALLEN  | SALESMAN  |
| WARD   | SALESMAN  |
| JONES  | MANAGER   |
| MARTIN | SALESMAN  |
| BLAKE  | MANAGER   |
| CLARK  | MANAGER   |
| SCOTT  | ANALYST   |
| KING   | PRESIDENT |
| TURNER | SALESMAN  |
| ADAMS  | CLERK     |
| JAMES  | CLERK     |
| FORD   | ANALYST   |
| MILLER | CLERK     |
+--------+-----------+

// 查询员工编号和员工姓名

mysql> select empno,ename from emp;
+-------+--------+
| empno | ename  |
+-------+--------+
|  7369 | SMITH  |
|  7499 | ALLEN  |
|  7521 | WARD   |
|  7566 | JONES  |
|  7654 | MARTIN |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7839 | KING   |
|  7844 | TURNER |
|  7876 | ADAMS  |
|  7900 | JAMES  |
|  7902 | FORD   |
|  7934 | MILLER |
+-------+--------+

// 查询员工的年薪?(字段可以参与数学运算)
select ename,sal * 12 from emp;

mysql> select ename,sal * 12 from emp;
+--------+----------+
| ename  | sal * 12 |
+--------+----------+
| 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 |
+--------+----------+

// 给查寻结果重命名
select ename,sal * 12 as yearsal from emp;

mysql>  select ename,sal * 12 as yearsal from emp;
+--------+----------+
| ename  | yearsal  |
+--------+----------+
| 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 |
+--------+----------+

// 起的别名中有中文
select ename,sal * 12 as ‘年薪’ from emp;

mysql> select ename,sal * 12 as '年薪' from emp;
+--------+----------+
| ename  | 年薪     |
+--------+----------+
| 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 |
+--------+----------+

注意:标准sql语句中字符串使用单引号括起来
as关键字可以省略

// 查询所有字段
select * from emp;

// 查询出工资等于5000的

select empno,ename,sal=5000 from emp;
+-------+--------+----------+
| empno | ename  | sal=5000 |
+-------+--------+----------+
|  7369 | SMITH  |        0 |
|  7499 | ALLEN  |        0 |
|  7521 | WARD   |        0 |
|  7566 | JONES  |        0 |
|  7654 | MARTIN |        0 |
|  7698 | BLAKE  |        0 |
|  7782 | CLARK  |        0 |
|  7788 | SCOTT  |        0 |
|  7839 | KING   |        1 |工资为5000
|  7844 | TURNER |        0 |
|  7876 | ADAMS  |        0 |
|  7900 | JAMES  |        0 |
|  7902 | FORD   |        0 |
|  7934 | MILLER |        0 |
+-------+--------+----------+

// 查询出工资小于5000的
select empno,ename,sal<5000 from emp;

mysql> select empno,ename,sal<5000 from emp;
+-------+--------+----------+
| empno | ename  | sal<5000 |
+-------+--------+----------+
|  7369 | SMITH  |        1 |
|  7499 | ALLEN  |        1 |
|  7521 | WARD   |        1 |
|  7566 | JONES  |        1 |
|  7654 | MARTIN |        1 |
|  7698 | BLAKE  |        1 |
|  7782 | CLARK  |        1 |
|  7788 | SCOTT  |        1 |
|  7839 | KING   |        0 |
|  7844 | TURNER |        1 |
|  7876 | ADAMS  |        1 |
|  7900 | JAMES  |        1 |
|  7902 | FORD   |        1 |
|  7934 | MILLER |        1 |
+-------+--------+----------+

// select empno,ename,sal<5000 ‘工资小于5000’ from emp;

mysql> select empno, ename, sal < 5000 '工资小于5000' from emp;

“as 关键字可以省略”
+-------+--------+------------------+
| empno | ename  | 工资小于5000     |
+-------+--------+------------------+
|  7369 | SMITH  |                1 |
|  7499 | ALLEN  |                1 |
|  7521 | WARD   |                1 |
|  7566 | JONES  |                1 |
|  7654 | MARTIN |                1 |
|  7698 | BLAKE  |                1 |
|  7782 | CLARK  |                1 |
|  7788 | SCOTT  |                1 |
|  7839 | KING   |                0 |
|  7844 | TURNER |                1 |
|  7876 | ADAMS  |                1 |
|  7900 | JAMES  |                1 |
|  7902 | FORD   |                1 |
|  7934 | MILLER |                1 |

11、条件查询

语法格式:
select
字段名,字段名…
from
表名
where
条件;

// 查询工资小于5000的工人编号,姓名

mysql> select
    -> empno,ename
    -> from
    -> emp
    -> where
    -> sal<5000;
+-------+--------+
| empno | ename  |
+-------+--------+
|  7369 | SMITH  |
|  7499 | ALLEN  |
|  7521 | WARD   |
|  7566 | JONES  |
|  7654 | MARTIN |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7844 | TURNER |
|  7876 | ADAMS  |
|  7900 | JAMES  |
|  7902 | FORD   |
|  7934 | MILLER |
+-------+--------+

// 查询工资等于5000的

mysql> select
    -> empno,ename
    -> from
    -> emp
    -> where
    -> sal=5000;
+-------+-------+
| empno | ename |
+-------+-------+
|  7839 | KING  |
+-------+-------+ 

// 查询’smith’的工资

mysql> select sal from emp where ename='smith';
+--------+
| sal    |
+--------+
| 800.00 |
+--------+

// 找出工资不等于3000的

mysql> select empno, ename from emp where sal<>3000;
+-------+--------+
| empno | ename  |
+-------+--------+
|  7369 | SMITH  |
|  7499 | ALLEN  |
|  7521 | WARD   |
|  7566 | JONES  |
|  7654 | MARTIN |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7839 | KING   |
|  7844 | TURNER |
|  7876 | ADAMS  |
|  7900 | JAMES  |
|  7934 | MILLER |
+-------+--------+

// 找出工资sal>=1100 and sal<=3000的

mysql> select ename,sal from emp where sal >= 1100 and sal <=3000;
mysql> select ename, sal from emp where sal between 1100 and 3000;(闭区间)

+--------+---------+
| ename  | sal     |
+--------+---------+
| ALLEN  | 1600.00 |
| WARD   | 1250.00 |
| JONES  | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| SCOTT  | 3000.00 |
| TURNER | 1500.00 |
| ADAMS  | 1100.00 |
| FORD   | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+

注意:between and在使用时必须前大后小(咦,这里好像不对,应该是前小后大吧)
between and不仅可以使用在数字方面也可以使用在字符方面

mysql> select ename from emp where ename between 'A' and 'C';
+-------+
| ename |
+-------+
| ALLEN |
| BLAKE |
| ADAMS |
+-------+

// 找出哪些人没有津贴?
// 在数据库中null不是一个值,代表什么也没有,为空。
// 空不是一个值,不能用等号来衡量。
// 判断是否为空,必须使用is null 或者 is not null

mysql> select ename,sal,comm from emp where comm 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 |
+--------+---------+------+

// 找出哪些人的津贴不为null?

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 |
+--------+---------+---------+

// 找出哪些人没有津贴?

mysql> select ename,sal,comm from emp where comm is null or comm = 0;
+--------+---------+------+
| 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 |
| TURNER | 1500.00 | 0.00 |
| ADAMS  | 1100.00 | NULL |
| JAMES  |  950.00 | NULL |
| FORD   | 3000.00 | NULL |
| MILLER | 1300.00 | NULL |
+--------+---------+------+

// 找出工作岗位是’salesman’和’president’的人

mysql> select ename, job from emp where job = 'salesman' or job = 'president';
+--------+-----------+
| ename  | job       |
+--------+-----------+
| ALLEN  | SALESMAN  |
| WARD   | SALESMAN  |
| MARTIN | SALESMAN  |
| KING   | PRESIDENT |
| TURNER | SALESMAN  |
+--------+-----------+

// 找出薪资大于1000并且部门编号为20或者30的员工

mysql> select ename,sal,deptno from emp where sal>1000 and deptno = 20 or empno = 30;(这个是有问题的)
+-------+---------+--------+
| ename | sal     | deptno |
+-------+---------+--------+
| JONES | 2975.00 |     20 |
| SCOTT | 3000.00 |     20 |
| ADAMS | 1100.00 |     20 |
| FORD  | 3000.00 |     20 |
+-------+---------+--------+ 

// and和or联合使用

mysql> select ename,sal,deptno from emp where sal>1000 and (deptno = 20 or deptno = 30);
mysql> select empno, ename, sal, deptno from emp where sal > 1000 and deptno in (20,30);
+--------+---------+--------+
| ename  | sal     | deptno |
+--------+---------+--------+
| ALLEN  | 1600.00 |     30 |
| WARD   | 1250.00 |     30 |
| JONES  | 2975.00 |     20 |
| MARTIN | 1250.00 |     30 |
| BLAKE  | 2850.00 |     30 |
| SCOTT  | 3000.00 |     20 |
| TURNER | 1500.00 |     30 |
| ADAMS  | 1100.00 |     20 |
| FORD   | 3000.00 |     20 |
+--------+---------+--------+

// in等同于or 找出工作岗位是’salesman’ 和 'manager’的所有员工

mysql> select ename,job from emp where job in ('salesman', 'manager');
mysql> select ename,job from emp where job = 'salesman' or job = 'manager';
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
mysql> select ename, job, sal from emp where sal in (1100, 5000);
// 这句的意思是找出工资是1100和5000的,不是一个区间 
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| KING  | PRESIDENT | 5000.00 |
| ADAMS | CLERK     | 1100.00 |
+-------+-----------+---------+

// not in 不在这几个值当中的

mysql> select ename,sal from emp where sal not in (1100, 5000);
+--------+---------+
| ename  | sal     |
+--------+---------+
| SMITH  |  800.00 |
| ALLEN  | 1600.00 |
| WARD   | 1250.00 |
| JONES  | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| SCOTT  | 3000.00 |
| TURNER | 1500.00 |
| JAMES  |  950.00 |
| FORD   | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+

// 模糊查询like
找出名当中有o的人
(在模糊查询中必须掌握两个特殊字符,一个是‘%’,一个是‘_’)
%代表任意多个字符,_代表任意一个字符
select ename from emp where ename like ‘%o%’;

mysql> select ename from emp where ename like '%o%';
+-------+
| ename |
+-------+
| JONES |
| SCOTT |
| FORD  |
+-------+

// 找出第二个字母是a的人
select ename from emp where ename like ‘_a%’;

mysql> select ename from emp where ename like '_a%';
+--------+
| ename  |
+--------+
| WARD   |
| MARTIN |
| JAMES  |
+--------+

// 找到名字中含有_的人
// 添加转义字符“\”让_变成普通字符

mysql> select id, name from t_user where name like ('%\_%');
+------+-----------+
| id   | name      |
+------+-----------+
|    2 | zhang_san |
+------+-----------+

// 找出名字最后一个字母是T的

mysql> select ename from emp where ename like ('%T');
+-------+
| ename |
+-------+
| SCOTT |
+-------+

// 排序
// 默认使用升序

mysql> select ename, sal from emp order by sal;
+--------+---------+
| 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 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| KING   | 5000.00 |
+--------+---------+

注意:降序使用desc [descending]
升序使用asc [ascending]

mysql> select ename, sal from emp order by sal asc;
+--------+---------+
| 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 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| KING   | 5000.00 |
+--------+---------+

// 按照工资的降序排列,当工资一样的时候,按照名字的升序排列。
// 只有当前面的字段无法排序的时候才会启用后面的字段
// 字段越靠前,越是起主导作用

mysql> select ename,sal from emp order by sal desc, ename asc;
按照题目要求排列		
+--------+---------+
| ename  | sal     |
+--------+---------+
| KING   | 5000.00 |
| 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 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SMITH  |  800.00 |
+--------+---------+

只按照工资降序排列

mysql> select ename,sal from emp order by sal 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 |
| WARD   | 1250.00 |
| MARTIN | 1250.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SMITH  |  800.00 |
+--------+---------+

// order by 可以按照字段的顺序进行排序

mysql> select ename, sal from emp  order by 2;		// 按照第二列进行排序
+--------+---------+
| 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 |
| SCOTT  | 3000.00 |
| FORD   | 3000.00 |
| KING   | 5000.00 |
+--------+---------+

// 找出员工职位是‘salesman’ 的员工并按照工资的降序排列。

mysql> select ename, job, sal from emp where job = 'salesman' order by sal desc;
mysql> select
    ->  ename, job, sal
    -> from
    ->  emp
    -> where
    ->  job = 'salesman'
    -> order by
    ->	sal desc;
+--------+----------+---------+
| ename  | job      | sal     |
+--------+----------+---------+
| ALLEN  | SALESMAN | 1600.00 |
| TURNER | SALESMAN | 1500.00 |
| WARD   | SALESMAN | 1250.00 |
| MARTIN | SALESMAN | 1250.00 |
+--------+----------+---------+

select 3
字段
from 1
表名
where 2
条件
order by 4

注意:order by是最后执行的

12、分组函数

count 计数
sum 求和
avg 求平均
max 最大值
min 最小值

注意:所有的分组函数都是对“某一组”数据进行操作的

// 求出工资总和

mysql> select sum(sal) from emp;
+----------+
| sum(sal) |
+----------+
| 29025.00 |
+----------+

// 求出工资最小值

mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+ 
|   800.00 |
+----------+

// 计算总人数

mysql> select count(ename) from emp;
+--------------+
| count(ename) |
+--------------+
|           14 |
+--------------+

分组函数共有5个
分组函数又叫做:多行处理函数
多行处理函数特点:输入多行,最终输出一行

*****分组函数自动忽略null

mysql> select count(comm) from emp;
+-------------+
| count(comm) | // comm中有null,但是计算结果不为null
+-------------+
|           4 |
+-------------+
mysql> select sum(comm) from emp;
	select sum(comm) from emp where comm is not null; // 不需要添加这个额外的过滤条件,sum函数自动忽略null
	+-----------+
	| sum(comm) |	// comm中有null,但是计算结果不为null,说明分组函数自动忽略null
	+-----------+
	|   2200.00 |
	+-----------+

// 找出工资高于平均工资的员工
平均工资

mysql> select avg(sal) from emp;
+-------------+
| avg(sal)    |
+-------------+
| 2073.214286 |
+-------------+
mysql> select ename, sal from emp where avg(sal);
		ERROR 1111 (HY000): Invalid use of group function
		// 思考以上错误信息?无效的使用了分组函数
		注意:SQL语句中有一个语法规则,分组函数不能直接使用在where子句中。

count(*)和count 某个字段 的区别?
count(*) 表示:不是统计某个字段中数据的条数,而是统计总记录条数
count comm 表示:comm字段中不为NULL的数据总数。

13、单行处理函数?

什么是单行处理函数?
输入一行,输出一行。

计算每个员工的年薪?
select ename, (sal + comm) * 12 as yearsal from emp;

mysql> select ename, sal, comm, (sal + comm) * 12 as yearsal from emp;
+--------+---------+---------+----------+
| ename  | sal     | comm    | yearsal  |
+--------+---------+---------+----------+
| SMITH  |  800.00 |    NULL |     NULL |
| ALLEN  | 1600.00 |  300.00 | 22800.00 |
| WARD   | 1250.00 |  500.00 | 21000.00 |
| JONES  | 2975.00 |    NULL |     NULL |
| MARTIN | 1250.00 | 1400.00 | 31800.00 |
| BLAKE  | 2850.00 |    NULL |     NULL |
| CLARK  | 2450.00 |    NULL |     NULL |
| SCOTT  | 3000.00 |    NULL |     NULL |
| KING   | 5000.00 |    NULL |     NULL |
| TURNER | 1500.00 |    0.00 | 18000.00 |
| ADAMS  | 1100.00 |    NULL |     NULL |
| JAMES  |  950.00 |    NULL |     NULL |
| FORD   | 3000.00 |    NULL |     NULL |
| MILLER | 1300.00 |    NULL |     NULL |
+--------+---------+---------+----------+

注意:所有数据库都是这样规定的,只要null参与运算,结果都为null

ifnull()空处理函数?
ifnull(可能为null的数据,被当作什么处理) // 单行处理函数

	mysql> select ename, (sal + ifnull(comm, 0)) * 12 from emp;
	+--------+------------------------------+
	| ename  | (sal + ifnull(comm, 0)) * 12 |
	+--------+------------------------------+
	| SMITH  |                      9600.00 |
	| ALLEN  |                     22800.00 |
	| WARD   |                     21000.00 |
	| JONES  |                     35700.00 |
	| MARTIN |                     31800.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 |
	+--------+------------------------------+

	mysql> select ename, ifnull(comm, 0) from emp;
	+--------+-----------------+
	| ename  | ifnull(comm, 0) |
	+--------+-----------------+
	| SMITH  |            0.00 |
	| ALLEN  |          300.00 |
	| WARD   |          500.00 |
	| JONES  |            0.00 |
	| MARTIN |         1400.00 |
	| BLAKE  |            0.00 |
	| CLARK  |            0.00 |
	| SCOTT  |            0.00 |
	| KING   |            0.00 |
	| TURNER |            0.00 |
	| ADAMS  |            0.00 |
	| JAMES  |            0.00 |
	| FORD   |            0.00 |
	| MILLER |            0.00 |
	+--------+-----------------+

14、group by 和 having

group by是对某个字段或者某些字段进行分组
having是对分组之后的数据进行再次过滤,having是group by 的搭档,只有group by出现的时候having才可以用

注意:分组函数一般和group by联合使用,这也是因为他为什么叫做分组函数的原因。
任何一个分组函数(max, min, avg, count, sum)都是在group by执行结束之后执行的。
当一条sql语句没有group by的时候,整张表的数据会自成一组。

分组函数不能直接使用在where子句当中?
因为group by是在where执行之后才会执行。

	select		5
		...
	from		1
		...	
	where		2  // 进行过滤 ,其后不能跟分组函数(多行处理函数)
		...
	group by	3  // 进行分组
		...
	having		4  // having是对自己分完组之后的数据不满意,再进行过滤
		...	
	order by	6  // 进行排序
		...

// 找出每一个工作岗位的最高薪资

mysql> select job, max(sal) from emp group by job;
+-----------+----------+
| job       | max(sal) |
+-----------+----------+
| ANALYST   |  3000.00 |
| CLERK     |  1300.00 |
| MANAGER   |  2975.00 |
| PRESIDENT |  5000.00 |
| SALESMAN  |  1600.00 |
+-----------+----------+

// 找出工资高于平均工资的员工

	mysql> select ename, sal from emp where sal > (select avg(sal) from emp);
// 记住一条规则:当
	+-------+---------+
	| ename | sal     |
	+-------+---------+
	| JONES | 2975.00 |
	| BLAKE | 2850.00 |
	| CLARK | 2450.00 |
	| SCOTT | 3000.00 |
	| KING  | 5000.00 |
	| FORD  | 3000.00 |
	+-------+---------+

// 每个工作岗位的平均薪资

mysql> select job, avg(sal) from emp group by job;
+-----------+-------------+
| job       | avg(sal)    |
+-----------+-------------+
| ANALYST   | 3000.000000 |
| CLERK     | 1037.500000 |
| MANAGER   | 2758.333333 |
| PRESIDENT | 5000.000000 |
| SALESMAN  | 1400.000000 |
+-----------+-------------+

// 多个字段能不能联合起来一块分组?
// 找出每个部门的不同工作岗位的最高薪资

mysql> select deptno, job, sal from emp order by deptno; // 从emp表中找出deptno, job, sal 按deptno排序
+--------+-----------+---------+
| deptno | job       | sal     |
+--------+-----------+---------+
|     10 | MANAGER   | 2450.00 |
|     10 | PRESIDENT | 5000.00 |
|     10 | CLERK     | 1300.00 |
|     20 | CLERK     |  800.00 |
|     20 | MANAGER   | 2975.00 |
|     20 | ANALYST   | 3000.00 |
|     20 | CLERK     | 1100.00 |
|     20 | ANALYST   | 3000.00 |
|     30 | SALESMAN  | 1600.00 |
|     30 | SALESMAN  | 1250.00 |
|     30 | SALESMAN  | 1250.00 |
|     30 | MANAGER   | 2850.00 |
|     30 | SALESMAN  | 1500.00 |
|     30 | CLERK     |  950.00 |
+--------+-----------+---------+

// 按照部门和职位分组,从emp中,找出最高工资。

select 
	deptno, job, max(sal)
from
	emp
group by 
	 deptno, job;
+--------+-----------+----------+
| deptno | job       | max(sal) |
+--------+-----------+----------+
|     10 | CLERK     |  1300.00 |
|     10 | MANAGER   |  2450.00 |
|     10 | PRESIDENT |  5000.00 |
|     20 | ANALYST   |  3000.00 |
|     20 | CLERK     |  1100.00 |
|     20 | MANAGER   |  2975.00 |
|     30 | CLERK     |   950.00 |
|     30 | MANAGER   |  2850.00 |
|     30 | SALESMAN  |  1600.00 |
+--------+-----------+----------+

// 找出每个部门的最高薪资,要求显示薪资大于2900的数据。
第一步:找出每个部门的最高薪资

mysql> select max(sal), deptno from emp group by deptno;
+----------+--------+
| max(sal) | deptno |
+----------+--------+
|  5000.00 |     10 |
|  3000.00 |     20 |
|  2850.00 |     30 |
+----------+--------+

第二步:找出薪资大于2900的

select max(sal) maxsal, deptno from emp group by deptno having maxsal > 2900; // 这种方式效率较低
+----------+--------+
| maxsal | deptno |
+----------+--------+
|  5000.00 |     10 |
|  3000.00 |     20 |
+----------+--------+

select max(sal), deptno from emp where sal > 2900 group by deptno; // 这种方式效率较高
+----------+--------+
| max(sal) | deptno |
+----------+--------+
|  5000.00 |     10 |
|  3000.00 |     20 |
+----------+--------+

// 找出每个部门的平均薪资,要求显示数据大于2000的数据。
第一步:找出每个部门的平均薪资

select deptno, avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+

第二步:显示大于2000的数据。

select deptno, avg(sal) from emp group by deptno having avg(sal) > 2000;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
+--------+-------------+
select deptno, avg(sal) from emp where avg(sal) > 2000 group by deptno; // 错误
// where之后不能使用分组函数
// 这种情况只能使用having过滤。

15、一个完整的数据查寻语句怎么写?(DQL)

select		5、对过滤分组,再过滤之后的数据查找出来
	...
from		1、通过from查询表
	...	
where		2、where条件过滤
	...
group by	3、group by分组(一个语句中有group by 的话,select中只能有参加分组的字段,以及这些字段的分组函数)
	...
having		4、having对分组之后的数据进行再次过滤
	...
order by	6、对查找出来的数据进行排序
	...

16、关于查询结果集的去重

mysql> select job from emp;
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| SALESMAN  |
| MANAGER   |
| SALESMAN  |
| MANAGER   |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
| SALESMAN  |
| CLERK     |
| CLERK     |
| ANALYST   |
| CLERK     |
+-----------+

mysql> select distinct job from emp;
// distinct 只能出现在所有字段的最前方。
// distinct 出现在所有字段的最前方,表示所有字段联合起来去除重复。
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+

// 实例:统计岗位的数量

mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) | 
+---------------------+
|                   5 |
+---------------------+

17、连接查询

17.1 什么是连接查询

实际开发中,大部分情况下都不是从单张表中查询数据,而是多张表联合查询,取出最终的结果。
实际开发中,一个业务一般对应多张表,比如:学生和班级。(假如学生和班级存一张表会出现数据的冗余)

17.2 连接查询的分类?

根据SQL出现的年代进行划分,包括:
SQL92
SQL99
根据表的连接方式进行划分:
内连接:
等值连接
非等值连接
自连接
外连接
左外连接(左连接)
右外连接(右连接)
全连接(很少用)

17.3 在表的连接查询方面有一个现象,叫做笛卡尔积现象(笛卡尔乘积现象)

// 找出每一个员工的部门名,要求显示部门名称和员工姓名。
select e.ename, d.dname from emp p, dept d;

mysql> select e.ename, d.dname from emp e, dept d;	// ename, dname 一块联合显示
+--------+------------+
| ename  | dname      |
+--------+------------+
| SMITH  | ACCOUNTING |
| SMITH  | RESEARCH   |
| SMITH  | SALES      |
| SMITH  | OPERATIONS |
| ALLEN  | ACCOUNTING |
| ALLEN  | RESEARCH   |
| ALLEN  | SALES      |
| ALLEN  | OPERATIONS |
| WARD   | ACCOUNTING |
| WARD   | RESEARCH   |
| WARD   | SALES      |
| WARD   | OPERATIONS |
| JONES  | ACCOUNTING |
| JONES  | RESEARCH   |
| JONES  | SALES      |
| JONES  | OPERATIONS |
| MARTIN | ACCOUNTING |
| MARTIN | RESEARCH   |
| MARTIN | SALES      |
| MARTIN | OPERATIONS |
| BLAKE  | ACCOUNTING |
| BLAKE  | RESEARCH   |
| BLAKE  | SALES      |
| BLAKE  | OPERATIONS |
| CLARK  | ACCOUNTING |
| CLARK  | RESEARCH   |
| CLARK  | SALES      |
| CLARK  | OPERATIONS |
| SCOTT  | ACCOUNTING |
| SCOTT  | RESEARCH   |
| SCOTT  | SALES      |
| SCOTT  | OPERATIONS |
| KING   | ACCOUNTING |
| KING   | RESEARCH   |
| KING   | SALES      |
| KING   | OPERATIONS |
| TURNER | ACCOUNTING |
| TURNER | RESEARCH   |
| TURNER | SALES      |
| TURNER | OPERATIONS |
| ADAMS  | ACCOUNTING |
| ADAMS  | RESEARCH   |
| ADAMS  | SALES      |
| ADAMS  | OPERATIONS |
| JAMES  | ACCOUNTING |
| JAMES  | RESEARCH   |
| JAMES  | SALES      |
| JAMES  | OPERATIONS |
| FORD   | ACCOUNTING |
| FORD   | RESEARCH   |
| FORD   | SALES      |
| FORD   | OPERATIONS |
| MILLER | ACCOUNTING |
| MILLER | RESEARCH   |
| MILLER | SALES      |
| MILLER | OPERATIONS |
+--------+------------+
56 rows in set (0.00 sec)

// 关于表的别名
别名的好处:
1、执行效率高
2、可读性好

17.4 怎么避免笛卡尔积现象?当然是加条件过滤。

避免了笛卡尔积现象,可以减少记录的匹配次数吗?
不能。笛卡尔积避免以后执行次数还是56次。只不过显示的是有效记录。
// 找出每一个员工的部门名,要求显示部门名称和员工姓名。

select 
		e.ename, d.dname 
	from
		emp e, dept d 
	where
		e.deptno = d.deptno;	// SQL92语法
	+--------+------------+
	| 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 |
	+--------+------------+
	14 rows in set (0.02 sec)

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

// 查询每个员工的部门编号,要求显示部门名称,员工姓名。

  • SQL92(太老了,不用了)
select
		e.ename, d.dname 
	from 
		emp e, dept d
	where
		e.deptno = d.deptno;
  • SQL99
select
		e.ename, d.dname
	from 
		emp e
	inner join
		dept d
	on 
		e.deptno = d.deptno;
// 语法:
	A
inner join
	B
on
	连接条件
where
	过滤条件
SQL99语法的好处:
	将表连接和where过滤分离

17.6 内连接之非等值连接,特点:连接条件中的关系是非等量关系。

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

mysql> select ename, sal from emp;
	+--------+---------+
	| ename  | sal     |
	+--------+---------+
	| SMITH  |  800.00 |
	| 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 |
	+--------+---------+
mysql> select * from salgrade;
	+-------+-------+-------+
	| GRADE | LOSAL | HISAL |
	+-------+-------+-------+
	|     1 |   700 |  1200 |
	|     2 |  1201 |  1400 |
	|     3 |  1401 |  2000 |
	|     4 |  2001 |  3000 |
	|     5 |  3001 |  9999 |
	+-------+-------+-------+

// inner可以省略

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 |
	+--------+---------+-------+

17.7 自连接。最大的特点是:一张表看作两张表,自己连自己。

// 找出每个员工的领导名,要求显示员工名和领导名。

mysql> select empno, ename, mgr from emp;
	+-------+--------+------+
	| empno | ename  | mgr  |
	+-------+--------+------+
	|  7369 | SMITH  | 7902 |
	|  7499 | ALLEN  | 7698 |
	|  7521 | WARD   | 7698 |
	|  7566 | JONES  | 7839 |
	|  7654 | MARTIN | 7698 |
	|  7698 | BLAKE  | 7839 |
	|  7782 | CLARK  | 7839 |
	|  7788 | SCOTT  | 7566 |
	|  7839 | KING   | NULL |
	|  7844 | TURNER | 7698 |
	|  7876 | ADAMS  | 7788 |
	|  7900 | JAMES  | 7698 |
	|  7902 | FORD   | 7566 |
	|  7934 | MILLER | 7782 |
	+-------+--------+------+

员工的领导编号 = 领导的员工编号

select a.ename as '员工名', b.ename as '领导名' from emp a inner join emp b on a.mgr = b.empno;
	+-----------+-----------+
	| 员工名    | 领导名    |
	+-----------+-----------+
	| 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     |
	+-----------+-----------+

18、外连接

18.1 什么是外连接?和内连接有什么区别?

  • 内连接:
    假设A表和B表进行连接,使用内连接,凡是A表B表可以匹配上的记录都查询出来,这就是内连接。
    AB表没有主副之分,是平等的。

  • 外连接:
    假设A表和B表进行连接,使用外连接,AB表有主副之分,其中一张是A表,一张是副表,主要
    查询主表中的内容,捎带查询副表中的内容,当副表中的内容没有和主表中的内容匹配上,
    副表自动模拟出NULL与之匹配。

18.2 外连接的分类:

左外连接(左边的表是主表):
右外连接(右边的表是主表):

左连接有右连接的写法,右连接也有对应的左连接的写法。

// 查询出所有员工及其所对应的领导,要求显示员工名和领导名
内连接:

select
		a.ename '员工名', b.ename '领导名'
from 
		emp a
join
		emp b
on 
		a.mgr = b.empno;
		+-----------+-----------+
		| 员工名    | 领导名    |
		+-----------+-----------+
		| 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     |
		+-----------+-----------+

外连接:

select
		a.ename '员工名', b.ename '领导名'
from 
		emp a			// 主表
left join
		emp b			// 副表
on 
		a.mgr = b.empno;

// 左连接的右连接写法

select
	a.ename '员工名', b.ename '领导名'
from 
	emp b			// 副表
right join
	emp a			// 主表
on 
			a.mgr = b.empno;
		+-----------+-----------+
		| 员工名     | 领导名     |
		+-----------+-----------+
		| SMITH     | FORD      |
		| ALLEN     | BLAKE     |
		| WARD      | BLAKE     |
		| JONES     | KING      |
		| MARTIN    | BLAKE     |
		| BLAKE     | KING      |
		| CLARK     | KING      |
		| SCOTT     | JONES     |
		| KING      | NULL      |	// 副表匹配不上,自动模拟NULL与之匹配
		| TURNER    | BLAKE     |
		| ADAMS     | SCOTT     |
		| JAMES     | BLAKE     |
		| FORD      | JONES     |
		| MILLER    | CLARK     |
		+-----------+-----------+

外连接最重要的特点是:主表的数据无条件的全部查询出来

实例:找出哪个部门没有员工?

select
			d.dname, e.ename
from 
			dept d
left join
			emp e
on 
			d.deptno = e.deptno;
		+------------+--------+
		| dname      | ename  |
		+------------+--------+
		| RESEARCH   | SMITH  |
		| SALES      | ALLEN  |
		| SALES      | WARD   |
		| RESEARCH   | JONES  |
		| SALES      | MARTIN |
		| SALES      | BLAKE  |
		| ACCOUNTING | CLARK  |
		| RESEARCH   | SCOTT  |
		| ACCOUNTING | KING   |
		| SALES      | TURNER |
		| RESEARCH   | ADAMS  |
		| SALES      | JAMES  |
		| RESEARCH   | FORD   |
		| ACCOUNTING | MILLER |
		| OPERATIONS | NULL   |		// 这个部门没有员工
		+------------+--------+
		15 rows in set (0.00 sec)	// 14个员工15条记录

// 正确写法

select
			d.*
from 
			dept d
left join
			emp e
on 
			d.deptno = e.deptno
where
			e.empno is null;
		+--------+------------+--------+
		| DEPTNO | DNAME      | LOC    |
		+--------+------------+--------+
		|     40 | OPERATIONS | BOSTON |
		+--------+------------+--------+

19、三张表怎么连接?

找出每个员工的部门名称,和工资等级
EMP表

mysql> select empno, ename, sal, deptno from emp;
		+-------+--------+---------+--------+
		| empno | ename  | sal     | deptno |
		+-------+--------+---------+--------+
		|  7369 | SMITH  |  800.00 |     20 |
		|  7499 | ALLEN  | 1600.00 |     30 |
		|  7521 | WARD   | 1250.00 |     30 |
		|  7566 | JONES  | 2975.00 |     20 |
		|  7654 | MARTIN | 1250.00 |     30 |
		|  7698 | BLAKE  | 2850.00 |     30 |
		|  7782 | CLARK  | 2450.00 |     10 |
		|  7788 | SCOTT  | 3000.00 |     20 |
		|  7839 | KING   | 5000.00 |     10 |
		|  7844 | TURNER | 1500.00 |     30 |
		|  7876 | ADAMS  | 1100.00 |     20 |
		|  7900 | JAMES  |  950.00 |     30 |
		|  7902 | FORD   | 3000.00 |     20 |
		|  7934 | MILLER | 1300.00 |     10 |
		+-------+--------+---------+--------+

DEPT表

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

SALGRADE表

mysql> select * from salgrade;
		+-------+-------+-------+
		| GRADE | LOSAL | HISAL |
		+-------+-------+-------+
		|     1 |   700 |  1200 |
		|     2 |  1201 |  1400 |
		|     3 |  1401 |  2000 |
		|     4 |  2001 |  3000 |
		|     5 |  3001 |  9999 |
		+-------+-------+-------+
select 
		e.ename, d.dname, e.sal, s.grade
from 
		emp e
join
		dept d
on	
		e.deptno = d.deptno
join
		salgrade s	
on
		e.sal between s.losal and s.hisal;
		+--------+------------+---------+-------+
		| ename  | dname      | sal     | grade |
		+--------+------------+---------+-------+
		| SMITH  | RESEARCH   |  800.00 |     1 |
		| ALLEN  | SALES      | 1600.00 |     3 |
		| WARD   | SALES      | 1250.00 |     2 |
		| JONES  | RESEARCH   | 2975.00 |     4 |
		| MARTIN | SALES      | 1250.00 |     2 |
		| BLAKE  | SALES      | 2850.00 |     4 |
		| CLARK  | ACCOUNTING | 2450.00 |     4 |
		| SCOTT  | RESEARCH   | 3000.00 |     4 |
		| KING   | ACCOUNTING | 5000.00 |     5 |
		| TURNER | SALES      | 1500.00 |     3 |
		| ADAMS  | RESEARCH   | 1100.00 |     1 |
		| JAMES  | SALES      |  950.00 |     1 |
		| FORD   | RESEARCH   | 3000.00 |     4 |
		| MILLER | ACCOUNTING | 1300.00 |     2 |
		+--------+------------+---------+-------+
		14 rows in set (0.00 sec)

找出每个员工的部门名称,和工资等级,以及上级领导

select
			a.ename '员工名', d.dname '部门名称', a.sal '薪资', s.grade '工资等级', b.ename '领导名'
from 
			emp a
left join
			emp b
on
			a.mgr = b.empno
join
			dept d
on	
			a.deptno = d.deptno
join
			salgrade s	
on
			a.sal between s.losal and s.hisal;
		+-----------+--------------+---------+--------------+-----------+
		| 员工名    | 部门名称     | 薪资    | 工资等级     | 领导名    |
		+-----------+--------------+---------+--------------+-----------+
		| SMITH     | RESEARCH     |  800.00 |            1 | FORD      |
		| ADAMS     | RESEARCH     | 1100.00 |            1 | SCOTT     |
		| JAMES     | SALES        |  950.00 |            1 | BLAKE     |
		| WARD      | SALES        | 1250.00 |            2 | BLAKE     |
		| MARTIN    | SALES        | 1250.00 |            2 | BLAKE     |
		| MILLER    | ACCOUNTING   | 1300.00 |            2 | CLARK     |
		| ALLEN     | SALES        | 1600.00 |            3 | BLAKE     |
		| TURNER    | SALES        | 1500.00 |            3 | BLAKE     |
		| JONES     | RESEARCH     | 2975.00 |            4 | KING      |
		| BLAKE     | SALES        | 2850.00 |            4 | KING      |
		| CLARK     | ACCOUNTING   | 2450.00 |            4 | KING      |
		| SCOTT     | RESEARCH     | 3000.00 |            4 | JONES     |
		| FORD      | RESEARCH     | 3000.00 |            4 | JONES     |
		| KING      | ACCOUNTING   | 5000.00 |            5 | NULL      |
		+-----------+--------------+---------+--------------+-----------+
		14 rows in set (0.00 sec)

20、什么是子查询?子查询都出现在哪里?

select语句中嵌套select语句,被嵌套的select语句是子查询
子查询可以出现在哪里?
select

from

where

20.1 where子句中使用子查询

案例:找出高于平均薪资的员工信息

  • 第一步:找出平均薪资
select avg(sal) from emp;
  • 第二步:找出高于平均薪资的员工信息
select
		*
	from
		emp
	where
		sal > (select avg(sal) from emp);
	+-------+-------+-----------+------+------------+---------+------+--------+
	| EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
	+-------+-------+-----------+------+------------+---------+------+--------+
	|  7566 | JONES | MANAGER   | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
	|  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 |
	|  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
	+-------+-------+-----------+------+------------+---------+------+--------+
	6 rows in set (0.00 sec)

20.2 from后面嵌套子查询

案例:找出每个部门平均薪水的薪资等级

  • 第一步:按照部门编号分组,找出每个部门的平均薪水
select
		deptno, avg(sal)
	from
		emp
	group by
		deptno;
	+--------+-------------+
	| deptno | avg(sal)    |
	+--------+-------------+
	|     10 | 2916.666667 |
	|     20 | 2175.000000 |
	|     30 | 1566.666667 |
	+--------+-------------+
	
  • 第二步:将上面这张表看作t表
select
		d.dname, s.grade
	from
		(select deptno, avg(sal) as avgsal from emp group by deptno) t
	join
		salgrade s
	on
		t.avgsal between s.losal and s.hisal
	join
		dept d
	on
		t.deptno = d.deptno;
	+------------+-------+
	| dname      | grade |
	+------------+-------+
	| SALES      |     3 |
	| ACCOUNTING |     4 |
	| RESEARCH   |     4 |
	+------------+-------+

案例:找出每个部门平均的薪水等级。

  • 第一步:找出每个员工的薪水等级。
select	e.deptno, e.ename, e.sal, s.grade from emp e join salgrade s on e.sal between losal and hisal;  
+--------+--------+---------+-------+
| deptno | ename  | sal     | grade |
+--------+--------+---------+-------+
|     20 | SMITH  |  800.00 |     1 |
|     30 | ALLEN  | 1600.00 |     3 |
|     30 | WARD   | 1250.00 |     2 |
|     20 | JONES  | 2975.00 |     4 |
|     30 | MARTIN | 1250.00 |     2 |
|     30 | BLAKE  | 2850.00 |     4 |
|     10 | CLARK  | 2450.00 |     4 |
|     20 | SCOTT  | 3000.00 |     4 |
|     10 | KING   | 5000.00 |     5 |
|     30 | TURNER | 1500.00 |     3 |
|     20 | ADAMS  | 1100.00 |     1 |
|     30 | JAMES  |  950.00 |     1 |
|     20 | FORD   | 3000.00 |     4 |
|     10 | MILLER | 1300.00 |     2 |
+--------+--------+---------+-------+	
  • 第二步:
select 
t.deptno, avg(t.grade) as '平均薪水等级' 
from 
(select e.deptno, e.ename, e.sal, s.grade from emp e join salgrade s on e.sal between losal and hisal) t 
group by t.deptno;
+--------+--------------------+
| deptno | 平均薪水等级       |
+--------+--------------------+
|     10 |             3.6667 |
|     20 |             2.8000 |
|     30 |             2.5000 |
+--------+--------------------+	

第二步中也可以不使用临时表进行查询

select	
	e.deptno, avg(s.grade) as '薪资平均等级' 
from 
	emp e 
join 
	salgrade s 
on 
	e.sal 
between 
	losal 
and 
	hisal
group by
	e.deptno;  
+--------+--------------------+
| deptno | 薪资平均等级       |
+--------+--------------------+
|     10 |             3.6667 |
|     20 |             2.8000 |
|     30 |             2.5000 |
+--------+--------------------+

20.3 select后嵌套子查询

// 找出每个员工所在部门名称,要求显示部门名称,员工姓名
以前使用的方法:

select
  e.ename, d.dname 
from
  emp e
join
  dept d
on 
  e.deptno = d.deptno;
+--------+------------+
| 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 |
+--------+------------+
14 rows in set (0.02 sec)
select       
  e.ename, (select d.dname from dept d where e.deptno = d.deptno) as dname 
from
  emp e;
+--------+------------+
| 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 |
+--------+------------+
14 rows in set (0.02 sec)

21、union (可以将查询结果集相加)

// 找出工作岗位是salesman,manager的员工

  • 第一种:select ename, job from emp where job = 'salesman' or job = 'manager';
  • 第二种:`select ename, job from emp where job in(‘salesman’, ‘manager’);
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
7 rows in set (0.02 sec)

第三种:使用union

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

union可以用在将两张不相干的表的数据拼接在一起
需要注意的是:两张表需要拼接在一块的数据列必须是一致的。

select ename from emp
union
select dname from dept;
+------------+
| ename      |
+------------+
| SMITH      |
| ALLEN      |
| WARD       |
| JONES      |
| MARTIN     |
| BLAKE      |
| CLARK      |
| SCOTT      |
| KING       |
| TURNER     |
| ADAMS      |
| JAMES      |
| FORD       |
| MILLER     |
| ACCOUNTING |
| RESEARCH   |
| SALES      |
| OPERATIONS |
+------------+
18 rows in set (0.00 sec)

22、limit (重点,分页查询全靠它)

22.1 limit是MySQL特有的,其他数据库没有,不通用。(Oracle中也有相同的机制,关键字是:rownum)

22.2 limit取结果集中的部分数据。这是它的作用。

22.3 limit语法机制

limit startIndex, length
startIndex :表示起始位置,从0开始,0表示第一条数据
length:表示取几个

案例:取出工资前5名的员工(降序取出前五个)
// 按照工资降序排列

mysql> select ename, sal from emp order by sal 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 |
| WARD   | 1250.00 |
| MARTIN | 1250.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| SMITH  |  800.00 |
+--------+---------+
14 rows in set (0.00 sec)

// 取出排序中工资的前五个数据
第一种写法:select ename, sal from emp order by sal desc limit 0, 5;
第二种写法:select ename, sal from emp order by sal desc limit 5;

+-------+---------+
| ename | sal     |
+-------+---------+
| KING  | 5000.00 |
| FORD  | 3000.00 |
| SCOTT | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.00 sec)

22.4 limit是sql语句种最后一个执行的。

select 5

from 1

where 2

group by 3

having 4

order by 6

limit 7

// 案例:找出工资排名在第四到第九名的员工

select
	ename, job, sal
from 
	emp
order by 
	sal desc
limit
	3, 6;
+--------+----------+---------+
| ename  | job      | sal     |
+--------+----------+---------+
| JONES  | MANAGER  | 2975.00 |
| BLAKE  | MANAGER  | 2850.00 |
| CLARK  | MANAGER  | 2450.00 |
| ALLEN  | SALESMAN | 1600.00 |
| TURNER | SALESMAN | 1500.00 |
| MILLER | CLERK    | 1300.00 |
+--------+----------+---------+
6 rows in set (0.00 sec)

// 分页显示:pageNo, pageSize
每页显示10条数据

第1页 limit 0, 3
第2页 limit 3, 3
第3页 limit 6, 3
第4页 limit 9, 3

第pageNO页 (pageSize - 1) * pageNo, pageNO
java代码{
int pageNO = 2; // 页码是2
int pageSize = 10; // 每页显示10条数据
limit (pageNO - 1) * pageSize, pageSize;
}

23、创建表

建表语句:
create table 表名 (
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,

);

如何删除一张表:
drop table if exists t_student; // 如果这张表存在的话,删除。

关于MySQL中的数据类型(以下只说常见的)
int 整数型(对应Java中的int类型)
bigint 长整型(对应Java中的long类型)
float 浮点型(对应Java中的float,double)
char 定长字符串(对应Java中的String类型)
varchar 可变长字符串(对应Java中的StringBuilder和StringBuffer)
date 日期类型(对应Java中的java.sql.date)
BLOB 二进制大对象(存储图片,视频,流媒体信息)Binary Large OBject(对应Java中的Object)
CLOB 字符大对象(存储大文本文件,例如:存储4G的字符串。)Character Large OBject(第一营Java中的Object)

char和varchar如何选择?
在实际开发中,当某个字段的数据长度不发生改变,是定长时,例如:生日,性别等,都使用char数据类型。
当一个字段的数据长度不确定,例如:姓名,简介等,使用varchar类型。

BLOB和CLOB的使用?
电影表:t_move
id(int) name(varchar) playtime(date/char) haibao(BLOB) history(CLOB)
1 蜘蛛侠
2
3

表名在数据库中一般建议使用:t_表名 或者 tbl_表名

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

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

24、insert插入数据

语法:insert into 表名(字段名1, 字段名2,字段名3,…) values(值1,值2,值3,…);
要求:字段的数量和值的数量相同,并且对应的数据类型相同。

insert into t_student (no, name, sex, classno, birth) values(1, 'zhangsan', '1', 'gaosan1ban');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
insert into t_student (no, name, sex, classno, birth) values(1, 'zhangsan', '1', 'gaosan1ban', '1998-12-26');
mysql> select *  from t_student;
+------+----------+------+------------+------------+
| no   | name     | sex  | classno    | birth      |
+------+----------+------+------------+------------+
|    1 | zhangsan | 1    | gaosan1ban | 1998-12-26 |
+------+----------+------+------------+------------+ 
insert into t_student (name, sex, classno, birth, no) values('lisi', '1', 'gaosan1ban', '2002-3-30', 2);
mysql> select * from t_student;
+------+----------+------+------------+------------+
| no   | name     | sex  | classno    | birth      |
+------+----------+------+------------+------------+
|    1 | zhangsan | 1    | gaosan1ban | 1998-12-26 |
|    2 | lisi     | 1    | gaosan1ban | 2002-3-30  |
+------+----------+------+------------+------------+
insert into t_student (name) values('wangwu');
mysql> select * from t_student;
+------+----------+------+------------+------------+
| no   | name     | sex  | classno    | birth      |
+------+----------+------+------------+------------+
|    1 | zhangsan | 1    | gaosan1ban | 1998-12-26 |
|    2 | lisi     | 1    | gaosan1ban | 2002-3-30  |
| NULL | wangwu   | NULL | NULL       | NULL       |
+------+----------+------+------------+------------+

删除表,重新建,重新插入

create table t_student(
	no bigint,
	name varchar(255),
	sex char(1) default 1,
	classno varchar(255),
	birth char(10)
);
insert into t_student (name) values('lisi');
+------+------+------+---------+-------+
| no   | name | sex  | classno | birth |
+------+------+------+---------+-------+
| NULL | lisi | 1    | NULL    | NULL  |
+------+------+------+---------+-------+

需要注意⚠️:
当一条insert语句执行成功之后,表格中必然会多出一行记录
即使这条记录中某些字段是NULL,后期也不能使用insert再进行插入
数据,只能使用update进行数据的更新。

// insert语句插入数据,可以对字段进行省略,但是对后面的values的数量和顺序都有要求。

insert into t_student values(1, 'zhangsan', 1, 'gaosan17', '1998-12-16');
+------+----------+------+----------+------------+
| no   | name     | sex  | classno  | birth      |
+------+----------+------+----------+------------+
| NULL | lisi     | 1    | NULL     | NULL       |
|    1 | zhangsan | 1    | gaosan17 | 1998-12-16 |
+------+----------+------+----------+------------+

// 一次插入多行数据

insert into t_student values(2, 'lisi', 1, 'gaosan16', '1998-06-16'),
		 (3, 'wangwu', 1, 'gaosan18', '1994-06-16'),
		 (4, 'xiaohong', 0, 'gaosan16', '1999-06-06');
mysql> select * from t_student;
+------+----------+------+----------+------------+
| no   | name     | sex  | classno  | birth      |
+------+----------+------+----------+------------+
| NULL | lisi     | 1    | NULL     | NULL       |
|    1 | zhangsan | 1    | gaosan17 | 1998-12-16 |
|    2 | lisi     | 1    | gaosan16 | 1998-06-16 |
|    3 | wangwu   | 1    | gaosan18 | 1994-06-16 |
|    4 | xiaohong | 0    | gaosan16 | 1999-06-06 |
+------+----------+------+----------+------------+

25、表的复制

语法:
create table 表名 as DQL语句;
将查询结果当作表创建出来

create table emp1 as select * from emp;

create table emp2 as select ename, job from emp;
mysql> select * from emp2;
+--------+-----------+
| ename  | job       |
+--------+-----------+
| SMITH  | CLERK     |
| ALLEN  | SALESMAN  |
| WARD   | SALESMAN  |
| JONES  | MANAGER   |
| MARTIN | SALESMAN  |
| BLAKE  | MANAGER   |
| CLARK  | MANAGER   |
| SCOTT  | ANALYST   |
| KING   | PRESIDENT |
| TURNER | SALESMAN  |
| ADAMS  | CLERK     |
| JAMES  | CLERK     |
| FORD   | ANALYST   |
| MILLER | CLERK     |
+--------+-----------+

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

语法:
insert into 表名 DQL语句;

create table dept1 as select * from dept;
insert into dept1 select * from dept;
mysql> select * from dept1;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

26、修改数据:update

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

注意:没有条件,整张表的数据全部更新

案例:将dept1表中的deptno = 10 的数据,dname改为’RENSHIBU’,LOC改为’SHANGHAI’

mysql> update dept1 set dname = 'RENSHIBU', LOC = 'SHANGHAI' where deptno = 10;
mysql> select * from dept1;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | RENSHIBU   | SHANGHAI |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
|     10 | RENSHIBU   | SHANGHAI |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

27、删除数据:delete

语法格式:delete from 表名 where 条件;
注意: 没有条件全部删除;

案例:删除10部门数据

delete from dept1 where deptno = 10;
mysql> select * from dept1;
+--------+------------+---------+
| DEPTNO | DNAME      | LOC     |
+--------+------------+---------+
|     20 | RESEARCH   | DALLAS  |
|     30 | SALES      | CHICAGO |
|     40 | OPERATIONS | BOSTON  |
|     20 | RESEARCH   | DALLAS  |
|     30 | SALES      | CHICAGO |
|     40 | OPERATIONS | BOSTON  |
+--------+------------+---------+

删除所有记录:

delete from dept1;
mysql> select * from dept1;
Empty set (0.00 sec)

如何删除大表中的数据?(重点)

truncate table 表名;	// 表被截断,不可回滚,永久丢失 (truncate截断的意思)
mysql> select * from emp1;
Empty set (0.00 sec)

如何删除表?
drop table 表名;(Oracle支持这种写法)
drop table if exists 表名;(Oracle不支持这种写法)

28、对表结构的操作(DDL)不讲,因为实际开发中对表结构的修改很少,如果修改是对以前设计的否定。

数据查询语言DQL(select)、数据操作语言DML(insert,delete\truncate,update)、数据定义语言DDL(create, drop, alter)

要是修改可以借助工具进行操作,修改表结构的代码不会出现在Java代码当中,出现在Java代码中的sql
包括:insert、delete、update、select(对数据的增删改查)

增删改查有一个术语:
CRUD 即:create(增)、retrieve(检索)、update(修改)、delete(删除)

29、约束(constraint)

29.1 什么是约束?常见的约束有哪些?

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

常见的约束有:

  • 非空约束(not null) 约束的字段不能为NULL
  • 唯一约束(unique) 约束的字段不能重复
  • 主键约束(primary key) 约束的字段既不能重复也不能为NULL(简称:PK)
  • 外键约束(foreign key) (简称fk)
  • 检查约束(check) 注意:Oracle数据库有check约束,但是MySQL目前不支持check约束。

表格

id username(唯一性约束) password(非空约束)


29.2 非空约束 not null

drop table if exists t_user;
// 建表
create table t_user (
	id int,
	username varchar(255) not null,
	password varchar(255)
);
insert into t_user (id, password) values(1, '123');
ERROR 1364 (HY000): Field 'username' doesn't have a default value

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

29.3 唯一性约束 unique

  • 唯一约束修饰的字段不能重复,但是可以为NULL,
  • 案例:
drop table if exists t_user;
create table t_user (
	id int,
	username varchar(255) unique
);
insert into t_user values(1, 'lisi');
insert into t_user values(1, 'lisi');
ERROR 1062 (23000): Duplicate entry 'lisi' for key 'username'
insert into t_user (id) values(2);
insert into t_user (id) values(3);
insert into t_user (id) values(4);
+------+----------+
| id   | username |
+------+----------+
|    1 | lisi     |
|    2 | NULL     |
|    3 | NULL     |
|    4 | NULL     |
+------+----------+
  • 案例: 给两个列或者多个列添加约束
drop table if exists t_user;
create table t_user (
	id int,
	usercode varchar(255),
	username varchar(255),
	unique(usercode, username)	// 表级约束   多个字段联合起来添加一个约束
);

insert into t_user (id, usercode, username) values(1, '111', 'ls');
insert into t_user (id, usercode, username) values(2, '111', 'zs');
insert into t_user (id, usercode, username) values(3, '222', 'ls');
mysql> select * from t_user;
+------+----------+----------+
| id   | usercode | username |
+------+----------+----------+
|    1 | 111      | ls       |
|    2 | 111      | zs       |
|    3 | 222      | ls       |
+------+----------+----------+
111ls和111zs不一样,联合起来的约束
insert into t_user(id, usercode, username) values(4, '111', 'ls');
ERROR 1062 (23000): Duplicate entry '111-ls' for key 'usercode'

drop table if exists t_user;
create table t_user (
	id int,
	usercode varchar(255) unique,
	username varchar(255) unique	// 列级约束
);

insert into t_user (id, usercode, username) values(1, '111', 'ls');
insert into t_user (id, usercode, username) values(2, '111', 'zs');
ERROR 1062 (23000): Duplicate entry '111' for key 'usercode'
mysql> select * from t_user;
+------+----------+----------+
| id   | usercode | username |
+------+----------+----------+
|    1 | 111      | ls       |
+------+----------+----------+
  • not null 只有列级约束,没有表级约束

29.4、主键约束

如何给一张表添加主键约束?

drop table if exists t_user;
create table t_user(
	id int primary key,
	username varchar(255),
	email varchar(255)
);

insert into t_user (id, username, email) values(1, 'lisi', 'lisi@163.com');
insert into t_user (id, username, email) values(2, 'wangwu', 'wangwu@163.com');
insert into t_user (id, username, email) values(3, 'zhaoliu', 'zhaoliu@163.com');
select * from t_user;
+----+----------+-----------------+
| id | username | email           |
+----+----------+-----------------+
|  1 | ls       | ls@163.com      |
|  2 | wangwu   | wangwu@163.com  |
|  3 | zhaoliu  | zhaoliu@163.com |
+----+----------+-----------------+
insert into t_user (id, username, email) values(1, 'zhouzhou', 'zhouzhou@163.com');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
insert into t_user (username, email) values('qianqian', 'qianqian@163.com');
ERROR 1364 (HY000): Field 'id' doesn't have a default value

⚠️根据以上测试,id字段添加了主键约束,不能为NULL,也不能重复。
主键的特点:不能为NULL,也不能重复

  • 主键相关术语
    主键约束:primary key
    主键字段:id字段添加primary key主键约束之后,id字段叫做,主键字段
    主键值:id字段中的每一个值,都是主键值

  • 主键有什么用?
    表的设计三范式中,第一范式要求任何一张表都应该有主键。
    主键的作用:主键值是这行记录在这张表中的唯一标识。(就像一个人的身份证号一样)。

  • 主键的分类?

    根据主键的字段数量来划分
    单一主键
    复合主键(多个字段联合起来添加一个主键约束)【复合主键不建议使用,因为其违背了三范式】
    根据主键性质划分
    自然主键:主键值最好和业务值没有任何关系的自然数(这种方式是推荐的)
    业务主键:主键值和系统的业务挂钩,例如:身份证号作为主键,银行卡号作为主键(不推荐使用)
    最好不要拿和业务相关的字段作为主键。因为一旦以后的业务发生改变的时候,主键值也需要发生改变,
    但是有时候不能发生变化。

  • 注意:一张表的主键约束只能有1个

  • 使用表级约束的方式定义主键

drop table if exists t_user;
create table t_user (
	id int,
	username varchar(255),
	primary key(id)
);

insert into t_user(id, username) values(1, 'lisi');
insert into t_user(id, username) values(2, 'zhangsan');
insert into t_user(id, username) values(3, 'wangwu');
insert into t_user(id, username) values(4, 'zhaoliu');
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | lisi     |
|  2 | zhangsan |
|  3 | wangwu   |
|  4 | zhaoliu  |
+----+----------+
  • 复合主键
drop table if exists t_user;
create table t_user (
	id int,
	username varchar(255),
	password varchar(255),
	primary key(id, username)

);
  • mysql提供的自增主键
drop table if exists t_user;
create table t_user(
	id int primary key auto_increment,    // id字段自动维护一个自增的数字,从1开始,以1递增。
	username varchar(255)
);

insert into t_user (username) values('a');
insert into t_user (username) values('a');
insert into t_user (username) values('a');
insert into t_user (username) values('a');
insert into t_user (username) values('a');
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | a        |
|  2 | a        |
|  3 | a        |
|  4 | a        |
|  5 | a        |
+----+----------+

29.5 外键约束

  • 关于外键约束的相关术语:
    外键约束:foreign key
    外键字段:添加有外键约束的字段,叫做外键约束
    外键值:外键字段中的每个值

  • 业务背景:
    请设计数据库表:存储所有学生和班级的信息?

    第一种方案:一张表存储所有数据

  no(pk)		name			classno			classname
  --------------------------------------------------------------------------------
  1			zs1			101			高三一班
  2			zs2			101			高三一班
  3			zs3			102			高三一班
  4			zs4			104			高三一班
  5			zs5			102			高三一班
  6			zs6			107			高三一班

缺点:数据冗余(不推荐)

第二种方案:两张表
t_student学生表(子表)
sno(pk) sname classno(给该字段添加外键约束fk)
1 zs1 101
2 zs2 101
3 zs3 103

​ t_class班级表(父表)
​ cno(pk) cname
​ 101 高三一班
​ 102 高三一班
​ 103 高三一班

  • 将以上表的建表语句写出来
    t_student表中的classno字段引用了t_class表中的cno字段,此时t_student表叫做子表,
    t_class表叫做父表。

    顺序:
    删除数据的时候先删除子表,再删除父表
    添加数据的时候先添加父表再添加子表。
    删除表的时候,先删除子表,再删除父表。
    添加表的时候,先添加父表,再添加子表。

drop table if exists t_student;
drop table if exists t_class;
create table t_class (
	cno int,
	cname varchar(255),
	primary key(cno)
);

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

insert into t_class values(101, 'xxxxxxxxxxxxxxxxxxxxxxxxxxx');
insert into t_class values(102, 'yyyyyyyyyyyyyyyyyyyyyyyyyyy');

insert into t_student values(1, 'ls1', 101);
insert into t_student values(2, 'ls2', 102);
insert into t_student values(3, 'ls3', 102);
insert into t_student values(4, 'ls4', 101);
select * from t_class;
select * from t_student;

insert into t_student values(5, 'ls5', 103);
ERROR 1452 (23000): Cannot add or update a child row: 
a foreign key constraint fails (`sqlstudy`.`t_student`, CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`cno`))
  • 外键值可以为NULL吗?
    外键值可以为NULL

  • 外键字段引用其他表中的字段的时候,这个字段必须是主键吗?
    外键引用不一定是主键,但是所引用字段需要具有唯一性

30、存储引擎?

30.1 完整的建表语句、

 CREATE TABLE `t_x` (
  `id` int(11) DEFAULT NULL
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

注意:MySQL中凡是标识符都可以使用飘号括起来的,但是其他数据库不行。````最好别用,不通用。
建表的时候可以指定引擎,和字符编码。
MySQL默认的存储引擎是INnoDB,字符集是utf8mb4。

30.2 什么是存储引擎?

存储引擎这个名字只在MySQL中这样叫,在Oracle中由对应的机制,但是不叫存储引擎,没有特殊的名字,就是表的存储方式。

MySQL支持各种不同的存储引擎,但是不同的存储引擎对应不同的存储方式,也有各自的优缺点

  • 查看当前MySQL支持的存储引擎?
show engines \G
     *************************** 1. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
	  XA: YES
  Savepoints: YES
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 5. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: MyISAM storage engine
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: CSV
     Support: YES
     Comment: CSV storage engine
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: Archive storage engine
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 8. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
	  XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: FEDERATED
     Support: NO
     Comment: Federated MySQL storage engine
Transactions: NULL
	  XA: NULL
  Savepoints: NULL
9 rows in set (0.01 sec)
 mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.18    |
+-----------+

mysql的这个版本支持的存储引擎的个数是9个

30.3 常见的存储引擎?

    Engine: MyISAM
	     Support: YES
	     Comment: MyISAM storage engine
	Transactions: NO		// 这种存储引擎不支持事务
		  XA: NO
	  Savepoints: NO
	  
	  
MyIsAM这种存储引擎不支持事务。
	  MyIsAM这种存储引擎是MySQL常用的存储引擎。
	  MyIsAM采用三个文件组织一张表:
		  xxx.frm(存储表格式的文件)
		  xxx.MYD(存储表中数据的文件)
		  xxx.MYI(存储表中索引的文件)
	  优点:可被压缩,节省存储空间。并且可以被转换成只读表,提高检索效率。
	  缺点:不支持事务。
	  ----------------------------------------------------------------------
	  ngine: InnoDB
	     Support: DEFAULT
	     Comment: Supports transactions, row-level locking, and foreign keys
	Transactions: YES
		  XA: YES
	  Savepoints: YES
	  优点:支持事务,行级锁,外键。这种存储引擎,数据安全得到保证。
	  表的结构存储在xxx.frm文件中
	  表的数据存储在tablespace这样的表空间中(逻辑概念)。因此不支持压缩,只读等。
	  这种INnoDB存储引擎,当MySQL数据库崩溃之后,提供数据自动恢复机制。
	  INnoDB支持级联删除和级联更新。
	  -----------------------------------------------------------------------------
	  Engine: MEMORY
	     Support: YES
	     Comment: Hash based, stored in memory, useful for temporary tables
	Transactions: NO
		  XA: NO
	  Savepoints: NO
	  缺点:不支持事务。因为所有数据索引存储在内存当中,数据容易丢失。表结构存储在xxx.frm文件中		
	  优点:查询速度最快
	  以前叫做HEAP引擎。

31、事务(transaction)

31.1 什么是事务?

事务是一个完整的业务逻辑单元,不可再分。
例如:银行账户转账:A账户向B账户转账10000,需要执行两条sql语句,这是一个完整的业务逻辑单元,要么同时失败,要么同时成功,这就是事务
update t_act set balance = balance - 10000 where actno = ‘act_001’;
update t_act set balance = balance + 10000 where actno = ‘act_002’;
以上两条DML语句,必须同时成功,或者同时失败,不允许一条成功一条失败。

要想保证以上两条DML语句同时成功或者同时失败就必须使用数据库的“事务机制”了。

31.2 和事务相关的语句只有:DML语句(delete、insert、update)

为什么?因为这三个语句都是和数据库中的数据相关的
事务的存在是为了保证数据的安全性,完整性。

31.3 假设所有的业务都可以使用一条DML语句完成,还需要事务吗?

不需要事务。
但实际情况不是这样的,通常一件事(事务【业务】)需要多条DML语句才可以完成。

31.4 事务的四大特性:ACID

  • A:原子性 【Atomicity】:事务是最小的工作单元,不可再分。
  • C:一致性 【consistency】:必须保证多条DML语句同时成功或者同时失败。
  • I:隔离性 【Isolation】:事务A和事务B之间具有隔离。
  • D:持久性 【durability】:持久性说的是数据最终必须持久化到硬盘文件中,事务才算成功的结束

31.5 关于事务之间的隔离性

事务之间的隔离性存在隔离级别,理论上隔离级别包括4个:

  • 第一级别:读未提交(read uncommitted)
    对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
    读未提交存在脏读现象(dirty read)现象:表示读到脏的数据。

  • 第二级别:读已提交(read committed)
    对方事务提交之后的数据,我方可以读取到。
    这种隔离级别解决了什么问题:解决了脏读现象。
    读已提交存在的问题是:不可重复读。

  • 第三级别:可重复读(repeatable read)
    这种隔离级别解决了:不可重复读问题。
    这种隔离级别存在的问题:读取到的数据是幻想。

  • 第四级别:序列化/串行化读(serializable)。
    解决了所有问题
    效率低。需要事务排队。【对一张表操作的一个事务还没有结束,不能再次去操作那张表】

    Oracle默认的事务隔离级别是:读已提交
    MySQL默认的事务隔离级别是:可重复读

    # MySQL查看事务的隔离级别:
    mysql> select @@global.transaction_isolation;    # mysql 8.0版本使用命令
    +--------------------------------+
    | @@global.transaction_isolation |
    +--------------------------------+
    | REPEATABLE-READ                |
    +--------------------------------+
    1 row in set (0.00 sec)
    

多个事务并发⚠️(同一时间段,多个任务同时执行,不是单位时间)运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)并发虽然是必须的,但是存在一下问题:

  • 脏读(Dirty read):一个事务正在访问数据库,并对数据进行了修改,这个修改还没有提交到数据库;另一个事务也访问了这个数据,并使用了这个数据,因为这个数据还没有提交,那么另一个事务读到的这个数据就是脏数据,依据脏数据所进行的操作可能是不正确的。即:使用未提交数据
  • 丢失修改(Lost to modify):指在一个事务读取一个数据的时候,另一个事务也访问了这个数据,那么在第一个事务修改了这个数据,另一个事务也修改了这个数据。第一个事务修改的结果丢失,称为丢失修改。eg:事务1读去A=20,事务2也读取A=20。事务1修改数据为A=A-1,结果是A=19。事务2修改数据为A=A-1,结果为19。即事务1的修改被丢失。即:修改再修改
  • 不可重复读(Unrepeatableread):一个事务中多次读取同一数据结果不一致。即,一个事务两次读取同一数据的间隙,另一事务对这一数据进行了修改,导致读取的数据结果不一致,叫做不可重复读。
  • 幻读(Phantom read):与不可重复读类似。一个事务(T1)读取一个数据几行的时候,另一个事务(T2)修改了数据。在随后的查询中,发现数据发生变化。就像幻觉一样。称为:幻读。

31.6 演示事务

mysql事务默认情况下是自动提交的。(什么是自动提交?只要执行一条DML语句,则提交一次)。
如何关闭自动提交:start transaction

准备表

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

演示:MySQL的事务是自动提交的,只要执行一次DML语句,就提交一次。
mysql> insert into t_user (username) values(‘ls’);
Query OK, 1 row affected (0.01 sec)

mysql> select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | ls       |
+----+----------+
1 row in set (0.00 sec)

mysql> rollback;		// 事务没有回滚成功
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | ls       |
    +----+----------+

演示:使用start transaction关闭自动提交机制
	mysql> start transaction;		// 关闭自动提交机制,开始一条事务
	Query OK, 0 rows affected (0.00 sec)

	mysql> insert into t_user (username) values('wangwu');
	Query OK, 1 row affected (0.00 sec)

	mysql> insert into t_user(username) values('zhaosi');
	Query OK, 1 row affected (0.00 sec)

	mysql> select * from t_user;
	+----+----------+
	| id | username |
	+----+----------+
	|  1 | ls       |
	|  2 | wangwu   |
	|  3 | zhaosi   |
	+----+----------+
	3 rows in set (0.00 sec)

	mysql> rollback;		// 回滚之后,剩余一条数据/记录
	Query OK, 0 rows affected (0.00 sec)

	mysql> select * from t_user;
	+----+----------+
	| id | username |
	+----+----------+
	|  1 | ls       |
	+----+----------+

	* 演示commit
	mysql> start transaction;
	Query OK, 0 rows affected (0.00 sec)

	mysql> insert into t_user(username) values('lisi');
	Query OK, 1 row affected (0.00 sec)

	mysql> insert into t_user(username) values('wangwu');
	Query OK, 1 row affected (0.00 sec)

	mysql> insert into t_user(username) values('rose');
	Query OK, 1 row affected (0.00 sec)

	mysql> insert into t_user(username) values('lily');
	Query OK, 1 row affected (0.00 sec)

	mysql> select * from t_user;
	+----+----------+
	| id | username |
	+----+----------+
	|  1 | ls       |
	|  4 | lisi     |
	|  5 | wangwu   |
	|  6 | rose     |
	|  7 | lily     |
	+----+----------+
	5 rows in set (0.00 sec)

	mysql> commit;
	Query OK, 0 rows affected (0.01 sec)

	mysql> rollback;		// rollback只能回滚到上一次的提交点 
	Query OK, 0 rows affected (0.00 sec)

	mysql> select * from t_user;
	+----+----------+
	| id | username |
	+----+----------+
	|  1 | ls       |
	|  4 | lisi     |
	|  5 | wangwu   |
	|  6 | rose     |
	|  7 | lily     |
	+----+----------+	

31.5 使用两个事务,演示以上的隔离级别。

  • 第一:演示read uncommitted;
    设置事务的隔离级别:set transaction isolation level read uncommitted;
    查看事务的全局隔离级别:select @@global.tx_isolation;
    ±----------------------+
    | @@global.tx_isolation |
    ±----------------------+
    | READ-UNCOMMITTED |
    ±----------------------+

  • 第二:演示read committed;

  • 第三:演示repeatable read;

  • 第四:演示serializable

32、索引

32.1 什么是索引?有什么用?

索引就相当于一本书的目录,通过索引可以快速找到对应的资源。
在数据库方面,查询一张表的时候有两种方式:
第一种:全表扫描
第二种:根据索引检索(效率很高)

索引为什么能提高检索效率?
其实最根本的原理是缩小了扫描范围。

索引虽然可以提高检索效率,但是不能随意的增加索引。索引也是数据库中的对象,
也是需要数据库不断的维护的。是有维护成本的。比如:表中的数据经常被修改,就不适合添加索引
因为数据一旦被修改,索引需要重新排序,进行维护。

添加索引是给某个字段,或者某些字段添加索引。

select ename, sal from emp where ename = 'smith';

当ename字段没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。
当ename字段添加了索引,以上sql语句会根据索引进行扫描,快速定位。

32.2 怎么创建索引对象?怎么删除索引对象?

创建索引对象
create index 索引名称 on 表名(字段名);

删除索引对象
drop index 索引名称 on 表名;

32.3 什么时候考虑给字段添加索引?(满足什么条件)

  • 数据俩庞大的时候(根据客户的需求,根据线上环境)

  • 该字段很少的DML操作的时候。(因为字段进行修改操作,索引也需要维护)

  • 该字段经常出现在where子句中。(经常根据哪个字段查询)

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

根据主键查询效率较高,尽量通过主键检索。

32.5 查看sql语句的执行计划

mysql> explain  select ename from emp where ename = 'smith';
	+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
	| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
	+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
	|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   14 |    10.00 | Using where |
	+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
  • 创建索引,通过索引去查
    给工资sal字段添加索引

    create index emp_sal_index on emp(sal);
    

    查看sql的执行计划。

    mysql> explain select ename from emp where sal = 5000;
    +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | emp   | NULL       | ref  | emp_sal_index | emp_sal_index | 9       | const |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
    

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

32.7 索引的实现原理

通过B Tree索效扫描范围,底层索引进行排序,分区,索引会携带数据在表中的“物理地址”,
最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的
select ename from emp where ename = ‘smith’;
通过索引转换为:
select ename from emp where 物理地址 = 0 x 3;

32.8 索引分类?

  • 单一索引:给单个字段添加索引
  • 复合索引:给多个字段添加1个索引
  • 主键索引:主键上会自动添加索引
  • 唯一索引:有unique约束的字段上会自动添加索引

32.9 索引什么时候失效?

select ename from emp where ename = ‘%A%’; // 模糊查询会使索引失效,即使给字段ename添加了索引
模糊查询的时候第一个通配符使用的是%,会使索引失效。

33 视图(view)

33.1 什么是视图?

站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。

33.2 怎么创建视图?怎么删除视图?

create view myview as select empno, ename from emp;  // 创建视图
drop view myview;  // 删除视图

注意:只有DQL语句才能以视图对象的方式创建出来。

33.3 对视图进行增删改查,会影响到原表中的数据。(通过视图影响原表中的数据的,不是直接操作原表)

可以对视图进行CRUD操作。

33.4 面向视图操作?

mysql> select * from myview;
+--------+-------+
| ename  | empno |
+--------+-------+
| SMITH  |  7369 |
| ALLEN  |  7499 |
| WARD   |  7521 |
| JONES  |  7566 |
| MARTIN |  7654 |
| BLAKE  |  7698 |
| CLARK  |  7782 |
| SCOTT  |  7788 |
| KING   |  7839 |
| TURNER |  7844 |
| ADAMS  |  7876 |
| JAMES  |  7900 |
| FORD   |  7902 |
| MILLER |  7934 |
+--------+-------+

create table emp1 as select * from emp;
create view myview1 as select ename, empno, sal from emp1;
update myview1 set ename = 'hehehe', sal = 20 where empno = 7329; // 通过视图修改原表中的数据
delete from myview1 where empno = 7369;  // 通过视图删除表中的数据 

33.5 视图的作用?

视图可以隐藏表的实现细节,保密级别较高的系统,数据库只对外提供相关的视图,Java程序员只对视图对象进行
CRUD。

34 DBA命令

34.1 将数据库中的数据导出

在windows的dos命令窗口上执行下面语句(导出整个库)
mysqldump sqlstudy>D:\sqlstudy.sql -uroot -p123456

在windows的dos命令窗口上执行下面语句(导出指定数据库中的指定表)
mysqldump sqlstudy>D:\sqlstudy.sql emp -uroot -p123456

34.2 导入数据

 create database sqlstudy;
 use sqlstudy;
 source D:\sqlstudy.sql

34.3 导出数据

35 数据库设计三范式(重点内容,面试经常提问)

35.1 什么是设计范式

设计表的依据,根据这个三范式设计出的表不会出现数据冗余。

35.2 三范式都是哪些?

  • 第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分。
  • 第二范式:建立在第一范式的基础上,所有非主键字段完全依赖主键,不能产生部分依赖。
    多对多? 关系表,两个外键
  • 第三范式:建立在第二范式的基础上,所有非主键字段直接依赖主键,不能产生传递依赖。
    一对多?两张表,多的表加外键。

在实际开发中,以客户的需求为主,有时候会拿数据冗余换执行速度。

35.3 一对一怎么设计?

一对一设计两种方案之:主键共享

t_user_login (用户登录表)
    id(pk)	username	password
    --------------------------------------------
    1		ls			123
    2		zs       	456

    
t_user_detail(用户详细信息表)
    id(pk + fk)	realname	tel
    ------------------------------------
    1		李四		111111111111
    2		张三		222222222222

一对一设计两种方案之:外键唯一

t_user_login (用户登录表)
    id(pk)	username	password
    --------------------------------------------
    1		ls			123
    2		zs       	456

t_user_detail(用户详细信息表)
    id(pk)	realname	tel		user_id(fk + unique) 【既是外键又是唯一性约束】
    ---------------------------------------------------------------------------------------------
    1		李四		111111111111	1
    2		张三		222222222222	2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值