碎话

  1. 本人整理资料时,发现了之前学习MySQL时做的笔记。笔记内容做的蛮好的,值得分享给大家。所以根据自己的学习能力、精力、空余时间情况,把笔记整理成了四天的学习章节。
  2. 每一个DQL、DML、DDL语句的学习,我都给出了具体的MySQL程序和运行结果。大家可以跟着敲一敲,或者当做复习资料。总的来说,实操用于是检验学习的不二法门。
  3. 相信大家全部看完会大有所获,有时间的话,我会将此篇文章单独整理成一个专栏(现在没时间)。
  4. 文中所用的数据库,有需要的同学可以在评论区留言邮箱号,我看到了就会发给大家。

文章目录

    • 碎话
  • @[toc]
    • 一、Day 01
      • 1-3、略
      • 4、看一下计算机上的服务
      • 5、在windows操作系统当中,怎么使用命令来启动和关闭MySQL服务?
      • 6、 mysql安装成功了,服务启动成功了,怎么使用客户端登录mysql数据库?
      • 7、mysql的常用命令【不见分号不执行】【不区分大小写】
      • 8、数据库中最基本的单元是表:table
      • 9、关于SQL语句的分类【要特别熟悉】?
      • 10、导入提前准备好的数据
      • 11、关于导入的这几张表?
      • 13、简单查询
        • 13.1 查询1个字段?
        • 13.2 查询2个字段,或多个字段?
        • 13.3 查询所有字段?
        • 13.4 给查询的列起别名?
        • 13.5 计算员工年薪?sal*12
      • 14、条件查询
        • 14.1 什么是条件查询
      • 15、排序
        • 15.1 排序查询所有员工薪资?
        • 15.2 可以两个字段排序吗?或者说按照多个字段排序?
        • 15.3 了解:根据字段的位置也可以排序
      • 16、综合一点的案例
        • 16.1 找出工资在1250到3000之间的员工信息,要求按照薪资降序排列
      • 17、数据处理函数/单行处理函数
        • 17.1 数据处理函数又被称为单行处理函数
        • 17.2 常见单行处理函数
      • 18、分组函数(多行处理函数)
      • 19、分组查询(*****非常重要:五颗星*****)
        • 19.1 什么是分组查询
        • 19.2 将之前关键字全部组合在一起,看他们的执行顺序
        • 19.3 找出每个工作岗位的工资和?
        • 19.4 找出部门的最高薪资
        • 19.5 找出每个部门,不同工作岗位的最高薪资
        • 19.6 找出每个部门最高薪资,要求显示最高薪资大于3000的?
        • 19.7 where没办法处理的情况?
      • 20、【回顾】
    • 二、Day 02[最重要]
      • 1、去除重复记录
      • 2、连接查询
        • 2.1 什么是连接查询
        • 2.2 连接查询的分类?
        • 2.3 当两张表进行连接查询时,没有任何条件的限制会发生什么现象?
        • 2.4 避免笛卡尔积现象
        • 2.5 内连接:等值连接
        • 2.6 内连接:非等值连接
        • 2.7 内连接之自连接
        • 2.8 外连接:右外连接、左外连接
        • 2.9 三张表、四张表怎么连接
      • 3、子查询
        • 3.1 什么是子查询?
        • 3.2 子查询都可以出现在哪里?
        • 3.3 where子句中的子查询
        • 3.4 from子句中的子查询
        • 3.5 select后面出现的子查询(了解)
      • 4、union合并查询结果集
      • 5、limit(非常重要)
        • 5.1 limit作用
        • 5.2 limit怎么用
        • 5.3 分页
      • 6、DQL语句的大总结
      • 7、表的创建(建表)
        • 7.1 建表的语法格式:(DDL语句,包括:create, drop, alter)
        • 7.2 关于mysql中的数据类型
        • 7.3 创建一个学生表?
        • 7.4 插入数据insert ( DML )
        • 7.5 insert插入日期
        • 7.6 date和datetime两个类型的区别
        • 7.7 update ( DML )
        • 7.8 delete(DML)
    • 三、Day 03
      • 1、查询每个员工的所在部门名称?要求显示员工名和部门名?
      • 2、insert语句可以一次插入多条记录【掌握】
      • 3、快速建表
      • 4、将查询结果插入到一张表中?insert相关
      • 5、快速删除表中的数据?【truncate比较重要,必须掌握,DDL操作】
      • 6、对表结构的增删改?【DDL,create drop alter,针对字段】
      • 7、约束(极其重要\****\*)
        • 7.1 什么是约束?
        • 7.2 约束包括哪些?
        • 7.3 非空约束:not null
        • 7.4 唯一性约束:unique
        • 7.5 主键约束(Primary key, PK,非常重要\****\*)
        • 7.6 外键约束(foreign key, PK, 非常重要)
        • 7.7 级联更新与级联删除
        • 7.8 删除约束
        • 7.9 添加约束
        • 7.10 修改约束
      • 8、存储引擎
        • 8.1 存储引擎的作用
        • 8.2 给表添加/指定“存储引擎”
        • 8.3 查看mysql支持的存储引擎
        • 8.4 mysql常用存储引擎
      • 9、事务(非常重要\****\*)
        • 9.1 什么是事务
        • 9.2 什么sql语句支持事务
        • 9.3 事务存在的意义
        • 9.4 事务的原理
        • 9.5 如何提交事务,如何回滚事务
        • 9.6 事务的ACID性质
        • 9.7 事务的5种状态
        • 9.7 **事务隔离级别**
        • 9.8 验证各种隔离级别
        • 9.9 设置服务器的缺省隔离级别
    • 三、Day 04
      • 1、索引
        • 1.1 什么是索引
        • 1.2 索引的实现原理
        • 1.3、mysql自动添加索引
        • 1.4 索引的优化
        • 1.5 索引的创建、删除
        • 1.6 查看SQL语句是否使用了索引进行检索
        • 1.7 索引失效(优化策略)
        • 1.8 数据库优化重要手段:索引
      • 2、视图(View)
        • 2.1 什么是视图
        • 2.2 创建/删除视图对象
        • 2.3 视图的作用:类似JAVA引用
        • 2.4 视图对象在实际开发中的作用
      • 3、DBA常用命令
        • 3.1 重点掌握
        • 3.2 数据导出
        • 3.3 数据导入
      • 4、数据库设计的三范式(重要)
        • 4.1 什么是数据库设计范式
        • 4.2 数据库设计三大范式
        • 4.3 第一范式
        • 4.4 第二范式
        • 4.5 第三范式
        • 4.6 总结表的设计(牢记)
        • 4.7 总结

一、Day 01

1-3、略

4、看一下计算机上的服务

5、在windows操作系统当中,怎么使用命令来启动和关闭MySQL服务?

语法:

net stop 服务名称;
net start 服务名称;

其他服务的启、停都可以用上述命令

6、 mysql安装成功了,服务启动成功了,怎么使用客户端登录mysql数据库?

使用bin目录下面的mysql.exe命令来连接mysql数据库服务器

本地登录(密码可见):

mysql -uroot -p123456

本地登录(密码不可见):

mysql -uroot -p

7、mysql的常用命令【不见分号不执行】【不区分大小写】

退出mysql:

exit

查看数据库管理系统中有哪些数据库:

show databases;

**【注意】**以英文分号‘ ; ’结尾;

查看数据库下有那些表?

show tables;

mysql默认自带4个数据库;

怎么选择使用某个数据库?

mysql> use test;

怎么创建数据库?

mysql>create database bjpowernode;

怎么查看表中的数据?

select * from 表名;

不看表中的数据,只看表的结构?

desc 表名;

查看mysql数据库的版本号

select version();

查看当前所使用的是哪个数据库?

select database;

【注意:不见 ; 不执行,; 是终止符】

\c用来终止命令
与ctrl+c作用一样

8、数据库中最基本的单元是表:table

什么是表table?为什么用表来存储数据呢?

​ 数据库当中以表格形式表示数据,因为表比较直观。

​ 任何一张表都有行和列:

​ 行(row):被称为数据/记录。

​ 列(column):被称为字段。

​ 姓名字段、性别字段、年龄字段。

【注意】:每一个字段都有:字段名、数据类型、约束等属性

字段名:见名知意即可;

数据类型:字符串、数字、日期等

约束:约束有较多

​ 唯一性约束:这种约束添加后,该字段中的数据不能重复

9、关于SQL语句的分类【要特别熟悉】?

​ SQL语句有很多,最好进行分门别类,这样更容易记忆。

​ DQL:数据参训语言(凡是带select关键字的都是查询语言)

​ select…

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

​ insert delete update

​ DDL:数据定义语言

​ 凡是带有creat、drop、alter的都是DDL

​ DDL主要操作的是表的结构,不是表中的数据

​ create:新建,等同于增

​ drop:删除

​ alter:修改

​ 这个增删改与DML不同,DDL主 要是对表结构进行操作

​ TCL:事务控制语言

​ 事务提交:commit;

​ 事务回滚:rollback;

​ DCL:数据控制语言

​ 例如:授权grant、撤销权限revoke…

10、导入提前准备好的数据

​ bjpowernode.sql 导入sql脚本文件,里面有表的创建

​ source table.sql直接执行table.sql脚本文件

source D:\course\03-MySQL\document\bjpowernode.sql

​ 【要先use 数据库;】

​ 【注意:路径不要有中文!!!】

【导入时出现问题

​ **Unknown command ‘\J’. **

​ **ERROR: Unknown command ‘\M’. **

ERROR: Unknown command ‘\M’.

这还是因为windows下路径的问题只需要改为把"“改为”/"】

11、关于导入的这几张表?

​ mysql> show tables;

​ dept:部门表

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

​ emp:员工表

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

​ salgrade:工资等级表

mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

​ 查看表中数据?

select * from 表名;

​ 不看表中的数据,只看表结构?

desc 表名;//【describe缩写为desc】
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO    | int         | NO   | PRI | NULL    |       |
| ENAME    | varchar(10) | YES  |     | NULL    |       |
| JOB      | varchar(9)  | YES  |     | NULL    |       |
| MGR      | int         | YES  |     | NULL    |       |
| HIREDATE | date        | YES  |     | NULL    |       |
| SAL      | double(7,2) | YES  |     | NULL    |       |
| COMM     | double(7,2) | YES  |     | NULL    |       |
| DEPTNO   | int         | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+

13、简单查询

13.1 查询1个字段?
select 字段名 from 表名;
【注意】:select和from是关键字,字段名和表名是标识符
【强调】:对所有SQL语句都是通用的,所有的SQL语句以“;”结尾SQL语句,不区分大小写
查询部门名字?
select dname from dept;
13.2 查询2个字段,或多个字段?
使用逗号隔开“,”查询部门编号和部门名?select deptno, dname from dept;
13.3 查询所有字段?
第一种方式:可以把所有字段都写上第二种方式:可以使用*(先转换为字段,再查询)缺点:1-效率低;2- 可读性差。在实际开发中不建议,在DOS命令中快速看一看全表数据可以采用这种方式
13.4 给查询的列起别名?
select deptno, dname as deptname from dept;

使用as关键字起别名

【注意】:只是将显示的查询结果列名显示为deptname,原列名还是叫dname

【记住】:select语句永远都不会进行修改操作(因为只负责查询)

as关键字可以省略吗?可以的

select deptno, dname  deptname from dept;

假设起别名的时候,别名里面有空格,怎么办?【编译器会报错】

select deptno, dname dept name from dept;

怎么解决?【单引号】

select deptno, dname ’dept name‘ from dept;//单引号select deptno, dname ”dept name“ from dept;//双引号

【注意】:在所有数据库中,字符串统一使用单引号’ ‘括起来,单引号是标准。双引号在oracle数据库中用不了。但是在mysql中可以使用。

【再次强调】:数据库中的字符串都是采用单引号括起来的。单引号 是标准,双引号不标准。

13.5 计算员工年薪?sal*12
 mysql> select ename, sal*12 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 |
+--------+----------+

14、条件查询

14.1 什么是条件查询

​ 不是将表中所有数据都查出来,而是查询符合条件的数据。

​ 语法格式:

​ select

​ 字段1,字段2,字段3,…

​ from

​ 表名

​ where

​ 条件;

​ = 等于 薪资等于3000的员工的empno和ename

mysql> select empno, ename from emp where sal = 3000;
+-------+-------+
| empno | ename |
+-------+-------+
|  7788 | SCOTT |
|  7902 | FORD  |
+-------+-------+

​ <>或!=不等于

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 |

​ < <= > >=

​ between … and … 两个值之间【增区间】,等同于 >= and <=

查询薪资在3000和5000之间的员工信息?包括3000和5000
mysql> select empno, ename from emp where sal between 3000 and 5000;
+-------+-------+
| empno | ename |
+-------+-------+
|  7788 | SCOTT |
|  7839 | KING  |
|  7902 | FORD  |
+-------+-------+mysql> select empno as '工号', ename as '姓名' from emp where sal >= 3000 and sal <= 5000;
+------+-------+
| 工号 | 姓名  |
+------+-------+
| 7788 | SCOTT |
| 7839 | KING  |
| 7902 | FORD  |
+------+-------+

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

查询哪些员工的津贴为null?mysql> select empno as '工号', ename as '姓名' from emp where comm is null;
+------+--------+
| 工号 | 姓名   |
+------+--------+
| 7369 | SMITH  |
| 7566 | JONES  |
| 7698 | BLAKE  |
| 7782 | CLARK  |
| 7788 | SCOTT  |
| 7839 | KING   |
| 7876 | ADAMS  |
| 7900 | JAMES  |
| 7902 | FORD   |
| 7934 | MILLER |
+------+--------+

​ and

​ or

查询工作岗位是MANAGER并且工资大于2500的员工信息?
mysql> select empno,ename,job,sal from emp where job = 'MANAGER'or 'SALESMAN' and sal > 2500;
+-------+-------+---------+---------+
| empno | ename | job     | sal     |
+-------+-------+---------+---------+
|  7566 | JONES | MANAGER | 2975.00 |
|  7698 | BLAKE | MANAGER | 2850.00 |
|  7782 | CLARK | MANAGER | 2450.00 |

and和or同时出现的话,有优先级问题吗?【and优先级高于or,故加( )】

【在开发中不确定优先级,就加( )】

mysql> select * from emp where sal > 2500 and deptno = 10 or deptno = 20;
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7369 | SMITH | CLERK     | 7902 | 1980-12-17 |  800.00 | NULL |     20 |
|  7566 | JONES | MANAGER   | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
|  7788 | SCOTT | ANALYST   | 7566 | 1987-04-19 | 3000.00 | NULL |     20 |
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
|  7876 | ADAMS | CLERK     | 7788 | 1987-05-23 | 1100.00 | NULL |     20 |
|  7902 | FORD  | ANALYST   | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+-------+-------+-----------+------+------------+---------+------+--------+mysql> select * from emp where sal > 2500 and (deptno = 10 or deptno = 20);
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7566 | JONES | MANAGER   | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
|  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 |
+-------+-------+-----------+------+------------+---------+------+--------+

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

【in不是一个区间,in后面跟的是具体的元素】

查询工作岗位是MANAGER和SALSMAN的员工
mysql> select empno,ename,job,sal from emp where job = 'manager' or 'salesman';mysql> select empno,ename,job,sal from emp where job in( 'manager' , 'salesman');
+-------+--------+----------+---------+
| empno | ename  | job      | sal     |
+-------+--------+----------+---------+
|  7499 | ALLEN  | SALESMAN | 1600.00 |
|  7521 | WARD   | SALESMAN | 1250.00 |
|  7566 | JONES  | MANAGER  | 2975.00 |
|  7654 | MARTIN | SALESMAN | 1250.00 |
|  7698 | BLAKE  | MANAGER  | 2850.00 |
|  7782 | CLARK  | MANAGER  | 2450.00 |
|  7844 | TURNER | SALESMAN | 1500.00 |
+-------+--------+----------+---------+

​ not 可以去非,主要用在is 或 in中

​ is null

​ is not null

​ in

​ not in

​ like like模糊查询,支持%或下划线匹配

​ %匹配任意多个字符

​ _下划线:匹配任意一个字符

​ (%是一个特殊字符,_也是一个特殊字符)

找到名字中含有o的员工?
select ename, empno from emp where ename like '%o%';
mysql> select ename, empno from emp where ename like '%o%';
+-------+-------+
| ename | empno |
+-------+-------+
| JONES |  7566 |
| SCOTT |  7788 |
| FORD  |  7902 |
+-------+-------+
找出名字以T结尾的员工?
mysql> select ename, empno from emp where ename like '%T';
+-------+-------+
| ename | empno |
+-------+-------+
| SCOTT |  7788 |
+-------+-------+
找出名字以姓A的员工?
mysql> select ename, empno from emp where ename like 'A%';
+-------+-------+
| ename | empno |
+-------+-------+
| ALLEN |  7499 |
| ADAMS |  7876 |
+-------+-------+
找出名字以第三个字符是R的员工?
mysql> select ename, empno from emp where ename like '__R%';
找出名字中有下划线'_'的员工?【 \   转移字符】
mysql> select name, no from t_student where name like '%\_%';
+----------+----+
| name     | no |
+----------+----+
| jack_son |  9 |
+----------+----+

15、排序

15.1 排序查询所有员工薪资?
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 |
+--------+---------+、
【指定降序】
mysql> select ename, sal from emp order by sal desc;//【descend】
mysql> select ename, sal from emp order by sal*-1;//【descend】
【指定升序】
mysql> select ename, sal from emp order by sal asc;【默认升序】
15.2 可以两个字段排序吗?或者说按照多个字段排序?
查询员工名字和薪资,要求按照【薪资升序】,【如果薪资一样】,则按照【名字降序】
mysql> select ename,sal from emp order by sal asc, ename desc;
+--------+---------+
| 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 |
+--------+---------+
15.3 了解:根据字段的位置也可以排序

【不健壮】:开发中不建议这样写,因为列的顺序容易改变

按照查询ename和sal,【根据第2列进行排序】
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 |
+--------+---------+

16、综合一点的案例

16.1 找出工资在1250到3000之间的员工信息,要求按照薪资降序排列
mysql> select empno, ename, job, sal from emp where sal between 1250 and 3000 order by sal desc;
+-------+--------+----------+---------+
| empno | ename  | job      | sal     |
+-------+--------+----------+---------+
|  7788 | SCOTT  | ANALYST  | 3000.00 |
|  7902 | FORD   | ANALYST  | 3000.00 |
|  7566 | JONES  | MANAGER  | 2975.00 |
|  7698 | BLAKE  | MANAGER  | 2850.00 |
|  7782 | CLARK  | MANAGER  | 2450.00 |
|  7499 | ALLEN  | SALESMAN | 1600.00 |
|  7844 | TURNER | SALESMAN | 1500.00 |
|  7934 | MILLER | CLERK    | 1300.00 |
|  7521 | WARD   | SALESMAN | 1250.00 |
|  7654 | MARTIN | SALESMAN | 1250.00 |
+-------+--------+----------+---------+
关键字顺序不能变:select...from...where...order by...以上语句的执行顺序必须掌握:第一步:from第二步:where第三步:select第四步:order by(排序总是在最后执行!)

17、数据处理函数/单行处理函数

17.1 数据处理函数又被称为单行处理函数

单行处理函数特点:一个输入对应一个输出(SISO)

和单行处理函数相对的是:多行处理函数,多个输入对应一个输出(MISO)。

17.2 常见单行处理函数

lower转换大小写函数(SISO)

mysql> select lower(ename) from emp;
【14个输入,最后还是14个输出】
+--------------+
| lower(ename) |
+--------------+
| smith        |
| allen        |
| ward         |
| jones        |
| martin       |
| blake        |
| clark        |
| scott        |
| king         |
| turner       |
| adams        |
| james        |
| ford         |
| miller       |
+--------------+

upper转换大小写(SISO)

mysql> select upper(ename) from emp;
+--------------+
| upper(ename) |
+--------------+
| SMITH        |
| ALLEN        |
| WARD         |
| JONES        |
| MARTIN       |
| BLAKE        |
| CLARK        |
| SCOTT        |
| KING         |
| TURNER       |
| ADAMS        |
| JAMES        |
| FORD         |
| MILLER       |
+--------------+

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

【不写长度,默认截取到最后】

【注意】:下标从1开始,没有0

找出员工名字第一个字符是A的员工信息?

第一种方式:模糊查询
mysql> select empno, ename, job, sal from emp where substr(ename, 1, 1) = 'A';
第二种方式:where中substr函数
mysql> select empno, ename, job, sal from emp where ename like 'A%';
+-------+-------+----------+---------+
| empno | ename | job      | sal     |
+-------+-------+----------+---------+
|  7499 | ALLEN | SALESMAN | 1600.00 |
|  7876 | ADAMS | CLERK    | 1100.00 |
+-------+-------+----------+---------+

首字母大写?【concat、upper、lower】

mysql> select concat(upper(substr(ename, 1, 1)),lower(substr(ename,2))) as result from emp;mysql> select concat(upper(substr(ename, 1, 1)),lower(substr(ename,2,length(ename)-1))) as result from emp;+--------+
| result |
+--------+
| Smith  |
| Allen  |
| Ward   |
| Jones  |
| Martin |
| Blake  |
| Clark  |
| Scott  |
| King   |
| Turner |
| Adams  |
| James  |
| Ford   |
| Miller |
+--------+

concat函数进行字符串拼接

select concat(empno, ename) from emp;

length取长度

mysql> select length(ename) enameLength from emp;
+-------------+
| enameLength |
+-------------+
|           5 |
|           5 |
|           4 |
|           5 |
|           6 |
|           5 |
|           5 |
|           5 |
|           4 |
|           6 |
|           5 |
|           5 |
|           4 |
|           6 |
+-------------+

trim去空格

mysql> select * from emp where ename = trim(' King');
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB       | MGR  | HIREDATE   | SAL     | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
|  7839 | KING  | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |     10 |
+-------+-------+-----------+------+------------+---------+------+--------+
1 row in set (0.00 sec)

str_to_date将字符串转换成日期

date_format格式化日期

format设置千分位

round(数据,小数点后位数) 【四舍五入】【小于0,则向小数点前置0】

【select 后跟某个表的字段名,也可以跟字面量和字面值】
select 字段 from 表名;
select ename from emp;
select abc from emp;//报错
select 'abc' from emp;//有几行记录,生成几行
select 1000 from emp;//有几行记录,生成几行
mysql> select 'abc' from dept;
+-----+
| abc |
+-----+
| abc |
| abc |
| abc |
| abc |
+-----+mysql> select round(1234.567, 1) result from dept;
+--------+
| result |
+--------+
| 1234.6 |
| 1234.6 |
| 1234.6 |
| 1234.6 |
+--------+

rand()生成随机数

mysql> select rand()*100 result from emp;
+--------------------+
| result             |
+--------------------+
|  66.96882645317244 |
| 55.673224251413004 |
|  77.45964497091215 |
| 20.278555173686293 |
|  69.01384402905948 |
|  84.23355769760306 |
| 14.126259474201369 |
| 17.930627351562144 |
|  47.27436140857112 |
|  82.57992806153365 |
|   71.0765591553194 |
| 7.6430146653605755 |
|  24.98539893420916 |
|  1.997953748328568 |
+--------------------+
mysql> select empno, ename from emp where rand() > 0.5;
+-------+--------+
| empno | ename  |
+-------+--------+
|  7499 | ALLEN  |
|  7566 | JONES  |
|  7654 | MARTIN |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7902 | FORD   |
|  7934 | MILLER |
+-------+--------+

ifnull(数据,为Null时当作哪个值) 可以将null转换为一个具体值

ifnull是空处理函数,专门处理空的

【注意】:因为在所有数据库中,只要null参与的数学运算,最终结果就一定是null。为了避免这个现象,需要使用ifnull函数。

计算每个月供的年薪?
年薪 = (月薪 + 月补助) * 12;
mysql> select empno, ename, (sal + comm) * 12 as yearsal from emp;
+-------+--------+----------+
| empno | ename  | yearsal  |
+-------+--------+----------+
|  7369 | SMITH  |     NULL |
|  7499 | ALLEN  | 22800.00 |
|  7521 | WARD   | 21000.00 |
|  7566 | JONES  |     NULL |
|  7654 | MARTIN | 31800.00 |
|  7698 | BLAKE  |     NULL |
|  7782 | CLARK  |     NULL |
|  7788 | SCOTT  |     NULL |
|  7839 | KING   |     NULL |
|  7844 | TURNER | 18000.00 |
|  7876 | ADAMS  |     NULL |
|  7900 | JAMES  |     NULL |
|  7902 | FORD   |     NULL |
|  7934 | MILLER |     NULL |
+-------+--------+----------+
mysql> select empno, ename, (sal + ifnull(comm,0)) * 12 as yearsal from emp;
+-------+--------+----------+
| empno | ename  | yearsal  |
+-------+--------+----------+
|  7369 | SMITH  |  9600.00 |
|  7499 | ALLEN  | 22800.00 |
|  7521 | WARD   | 21000.00 |
|  7566 | JONES  | 35700.00 |
|  7654 | MARTIN | 31800.00 |
|  7698 | BLAKE  | 34200.00 |
|  7782 | CLARK  | 29400.00 |
|  7788 | SCOTT  | 36000.00 |
|  7839 | KING   | 60000.00 |
|  7844 | TURNER | 18000.00 |
|  7876 | ADAMS  | 13200.00 |
|  7900 | JAMES  | 11400.00 |
|  7902 | FORD   | 36000.00 |
|  7934 | MILLER | 15600.00 |
+-------+--------+----------+

case…when…then…when…then…else…end【相当于switch case default】

当员工岗位是MANAGER时,工资上调10%,为SALESMAN时上调50%
mysql> select empno, ename, job, sal, case job when 'manager' then sal*1.1 when 'salesman' then sal*1.5 else sal end newsal from emp;
+-------+--------+-----------+---------+---------+
| empno | ename  | job       | sal     | newsal  |
+-------+--------+-----------+---------+---------+
|  7369 | SMITH  | CLERK     |  800.00 |  800.00 |
|  7499 | ALLEN  | SALESMAN  | 1600.00 | 2400.00 |
|  7521 | WARD   | SALESMAN  | 1250.00 | 1875.00 |
|  7566 | JONES  | MANAGER   | 2975.00 | 3272.50 |
|  7654 | MARTIN | SALESMAN  | 1250.00 | 1875.00 |
|  7698 | BLAKE  | MANAGER   | 2850.00 | 3135.00 |
|  7782 | CLARK  | MANAGER   | 2450.00 | 2695.00 |
|  7788 | SCOTT  | ANALYST   | 3000.00 | 3000.00 |
|  7839 | KING   | PRESIDENT | 5000.00 | 5000.00 |
|  7844 | TURNER | SALESMAN  | 1500.00 | 2250.00 |
|  7876 | ADAMS  | CLERK     | 1100.00 | 1100.00 |
|  7900 | JAMES  | CLERK     |  950.00 |  950.00 |
|  7902 | FORD   | ANALYST   | 3000.00 | 3000.00 |
|  7934 | MILLER | CLERK     | 1300.00 | 1300.00 |
+-------+--------+-----------+---------+---------+

18、分组函数(多行处理函数)

特点:

  1. 输出多行,输出一行

  2. 分组函数自动忽略null(认为没有)

  3. 分组函数中count(*):【统计总表行不为null的元素总数】和count(字段):【统计该字段下所有不为null的元素的总数】

  4. 数据库中不可能存在某行记录列元素均为null

  5. 分组函数不能直接使用在where子句中

    mysql> select empno from emp where sal > sum(sal);//报错
    
  6. 所有的分组函数可以组合使用,不能嵌套

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

【5个:

​ count计数

​ sum求和

​ avg平均值

​ max最大值

​ min最大值】

【注意】:分组函数在使用前必须先进行分组,再使用。否则,整张表作为一组。

找出最高工资?

mysql> select empno, ename, max(sal) from emp;
+-------+-------+----------+
| empno | ename | max(sal) |
+-------+-------+----------+
|  7369 | SMITH |  5000.00 |
+-------+-------+----------+

找出最低工资?

mysql> select empno, ename, min(sal) from emp;
+-------+-------+----------+
| empno | ename | min(sal) |
+-------+-------+----------+
|  7369 | SMITH |   800.00 |
+-------+-------+----------+

计算工资和?

mysql> select sum(comm) from emp;
+-----------+
| sum(comm) |
+-----------+
|   2200.00 |
+-----------+

计算平均工资?

mysql> select empno, ename, avg(sal) from emp;
+-------+-------+-------------+
| empno | ename | avg(sal)    |
+-------+-------+-------------+
|  7369 | SMITH | 2073.214286 |
+-------+-------+-------------+
mysql> select avg(ifnull(comm,0)) from emp;
+---------------------+
| avg(ifnull(comm,0)) |
+---------------------+
|          157.142857 |
+---------------------+

统计员工数量?

mysql> select empno, ename, count(sal) umpNumber from emp;
+-------+-------+-----------+
| empno | ename | umpNumber |
+-------+-------+-----------+
|  7369 | SMITH |        14 |
+-------+-------+-----------+
mysql> select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
|           4 |
+-------------+

19、分组查询(非常重要:五颗星

19.1 什么是分组查询

在实际应用中,可能有这样需求,需要先分组【比如按照工作岗位分组】,再对每一组数据进行操作,这时需要分组查询。不分组默认整个表为1组

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

​ 计算每个部门的工资和?

​ 计算每个工作岗位的平均薪资?

​ 找出每个工作岗位的最高薪资?

​ …

19.2 将之前关键字全部组合在一起,看他们的执行顺序
select...
from...
where...
group by...
order by...

执行顺序不能颠倒,需要记忆:【具有优先级,不能颠倒】

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

为什么分组函数不能直接使用在where后面?

mysql> select empno from emp where sal > sum(sal);//报错

因为分组函数在使用的时候必须先分组才能使用,【where执行的时候还没有分组】,所以where后面不能出现分组函数,【出现了语法错误】

select sum(sal) from emp;

这个没分组,为什么sum()可以使用?

因为select在group by之后执行

19.3 找出每个工作岗位的工资和?

【思路】:按照工作岗位分组,然后对工资求和

mysql> select job,sum(sal) from emp group by job;
+-----------+----------+
| job       | sum(sal) |
+-----------+----------+
| CLERK     |  4150.00 |
| SALESMAN  |  5600.00 |
| MANAGER   |  8275.00 |
| ANALYST   |  6000.00 |
| PRESIDENT |  5000.00 |
+-----------+----------+

执行顺序?

1. 先从emp标中查询数据
2. 过呢据job字段进行分组
3. 然后对每一组的数据进行sum(sal)

下列语句在mysql中可以执行,但是毫无意义。在oracle中会报错(mysqll语法相对松散)

mysql> select ename, job, sum(sal) from emp group by job;
+-------+-----------+----------+
| ename | job       | sum(sal) |
+-------+-----------+----------+
| SMITH | CLERK     |  4150.00 |
| ALLEN | SALESMAN  |  5600.00 |
| JONES | MANAGER   |  8275.00 |
| SCOTT | ANALYST   |  6000.00 |
| KING  | PRESIDENT |  5000.00 |
+-------+-----------+----------+

【重点结论】:

  1. 在一条select语句中,如果有group by语句,那么select后面只能跟:

    1. 参加分组的字段
    2. 分组函数
    3. 其它的一律不能跟
19.4 找出部门的最高薪资

【思路】:先按照部门编号分组,求每一组的最大值

【表连接】:这样能找到最大值薪资是谁。通过临时表进行连接

mysql> select deptno, avg(sal),sum(sal), max(sal) from emp group by deptno order by deptno [desc];
+--------+-------------+----------+----------+
| deptno | avg(sal)    | sum(sal) | max(sal) |
+--------+-------------+----------+----------+
|     10 | 2916.666667 |  8750.00 |  5000.00 |
|     20 | 2175.000000 | 10875.00 |  3000.00 |
|     30 | 1566.666667 |  9400.00 |  2850.00 |
+--------+-------------+----------+----------+
19.5 找出每个部门,不同工作岗位的最高薪资

【思路】:同时分组。先对部门分组,再对岗位分组

【技巧】:多个字段联合成1个字段

select deptno, job, max(sal)
fromemp
group bydeptno, job;
mysql> select deptno, job, max(sal) from emp group by deptno,job order by deptno;
+--------+-----------+----------+
| 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 |
+--------+-----------+----------+
19.6 找出每个部门最高薪资,要求显示最高薪资大于3000的?

【思路1】:先分组再筛选

  1. 按照部门编号分组group by,求每一组最大值max
mysql> select deptno, max(sal) > 3000 from emp group by deptno;
+--------+-----------------+
| deptno | max(sal) > 3000 |
+--------+-----------------+
|     20 |               0 |
|     30 |               0 |
|     10 |               1 |
+--------+-----------------+
mysql> select deptno, max(sal) from emp group by deptno;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
|     20 |  3000.00 |
|     30 |  2850.00 |
|     10 |  5000.00 |
+--------+----------+
  1. 要求显示最高薪资大于3000
selectdeptno, max(sal)
fromemp
group bydeptno
havingmax(sal) > 3000;mysql> select deptno, max(sal) from emp group by deptno having max(sal) > 3000;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
|     10 |  5000.00 |
+--------+----------+

【思路2】:先筛选再分组

实际上思路1效率比较低,可以先将>3000的找出来,再分组

selectdeptno, max(sal)
fromemp
wheresal > 3000
group bydeptno;mysql> select empno, max(sal) from emp where max(sal) > 3000 group by deptno;
ERROR 1111 (HY000): Invalid use of group function
【属于先where再max分组,报错】mysql> select empno, max(sal) from emp where sal > 3000 group by deptno;
+-------+----------+
| empno | max(sal) |
+-------+----------+
|  7839 |  5000.00 |
+-------+----------+
1 row in set (0.00 sec)

【where效率高于having】

19.7 where没办法处理的情况?

找出每个部门的平均薪资高于2500的工作

【where后面只能用表里已知的字段】

【思路】:不能不使用having

  1. 找出每个部门的平均【分组了】薪资
mysql> select deptno, avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     20 | 2175.000000 |
|     30 | 1566.666667 |
|     10 | 2916.666667 |
+--------+-------------+
  1. 要求显示平均薪资【分组了】高于2500的
mysql> select deptno, avg(sal) from emp group by deptno having avg(sal) > 2500;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
+--------+-------------+

20、大总结(单表的查询学完了)

select...
where...
group by...
having...
order by...
语法只能严格按照上述顺序,不能颠倒执行顺序:
1. from
2. where
3. group by
4. having
5. select
6. order by执行的逻辑顺序:
1. from 某张表中查询数据;
2. 先经过 where 条件【表中已存在的字段】筛选出有价值的数据;
3. 对这些有价值的数据进行分组 group by,
4. 分组后可以继续用 having 继续筛选;
5. 接着使用 select 查询出来;
6. 最后用 order by排序。

【综合题】:找出部门的每个岗位的平均薪资,要求显示平均薪资大于1500的,除了manager岗位之外,要求按照平均薪资降序排列。

mysql> select deptno, job, avg(sal) from emp where job <> 'manager' group by job having avg(sal) > 1500 order by avg(sal) desc;
+--------+-----------+-------------+
| deptno | job       | avg(sal)    |
+--------+-----------+-------------+
|     10 | PRESIDENT | 5000.000000 |
|     20 | ANALYST   | 3000.000000 |
+--------+-----------+-------------+
mysql> select deptno, job, avg(sal) avgSal from emp where job not in ( 'manager') group by job having avg(sal) > 1500 order by avgSal desc;
+--------+-----------+-------------+
| deptno | job       | avgSal      |
+--------+-----------+-------------+
|     10 | PRESIDENT | 5000.000000 |
|     20 | ANALYST   | 3000.000000 |
+--------+-----------+-------------+

20、【回顾】

DBMS ---> SQL ---> DBMySQL(开源免费)、oracle(世界上速度最快、安全级别最高、后期服务昂贵)、db2、sybase...是DBMSmysql安装:port 3306用户名:root密码:123456设置字符集:utf8SQL 分类DQL(Data Query Language 数据查询语言): select,只查询不会修改表DML(Data Manipulation Language 数据操纵语言->表数据): insert, delete, updateDDL(Data Definition Language 数据定义语言->表结构): create, drop, alterTCL(Transactional Control Language 事务控制语言): commit, rollbackDCL(Data Control Language 数据控制语言->权限): grant, revoke导入演示数据1. 连接MySQL2. 创建'bjpowernode'数据库create database bjpowernode;3. 选择数据库use bjpowernode;4. source导入数据库source D:\course\03-MySQL\document\bjpowernode.sql5. 查看表结构desc dept;常用MySQL命令【 select 语句总结】select ...from...where...group by...having...order by...以上关键字只能按照这个顺序来,不能颠倒。执行顺序?1. from2. where3. group by4. having5. select6. order by

二、Day 02[最重要]

1、去除重复记录

【注意】:元彪数据不会被修改,只是修改了查询结果

【关键字】:distinct,只能出现在所有字段的最前方,表示后面的字段联合起来去重

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

统计工作岗位的数量?

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

2、连接查询

2.1 什么是连接查询

从一张表中单独查询,称为单表查询

emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中查询工作地点

这种跨表查询,多张表联合起来查询数据,被称为【连接查询】

2.2 连接查询的分类?

根据语法的年代分类:

SQL92:1992年出现的语法

SQL99:1999年出现的语法【重点学习】

根据表连接的方式分类:

  1. 内连接 【完全能匹配条件的数据,查询出来】

    1. 等值连接
    2. 非等值连接
    3. 自连接
  2. 外连接 【外连接】:相当于内连接+主表没有匹配的行
    1. 左外连接(左连接)
    2. 右外连接(右连接)
  3. 全连接(不讲)
2.3 当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

【案例】:查询每个员工所在部门名称

  1. 当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数是两个表条数的乘积。

    【笛卡尔积现象】:查询多个表时,没有添加有效的条件,导致多个表所有行完全连接。

mysql> select ename, dname from emp, dept;
+--------+------------+
| ename  | dname      |
+--------+------------+
| SMITH  | OPERATIONS |
| SMITH  | SALES      |
| SMITH  | RESEARCH   |
| SMITH  | ACCOUNTING |
...
| MILLER | OPERATIONS |
| MILLER | SALES      |
| MILLER | RESEARCH   |
| MILLER | ACCOUNTING |
+--------+------------+
14*4 = 56 rows in set (0.00 sec)
2.4 避免笛卡尔积现象
  1. 连接时加条件 where ,满足这个条件的才会被筛选出来!

【匹配次数并没有被减少,还是匹配了56次,只是被筛选出了1/4】

【需要找到两个表中重合的键】

mysql> select ename, dname from emp, dept where emp.deptno = dept.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.00 sec)

【起别名】:表中起别名,对查询范围进行限制。很重要。效率问题。

mysql> select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno;//92语法
+--------+------------+
| 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 |
+--------+------------+

【注意】:由笛卡尔积现象得出:表的连接次数越多,效率越低,尽量避免表的连接次数。

2.5 内连接:等值连接

【案例】:查询每个员工所在部门名称,显示员工名和部门名?

【思路】:emp e和dept d表进行连接,条件是:e.deptno = d.deptno

SQL:1992select e.ename,d.dnamefromemp e, dept dwheree.deptno = d.deptno and 后面加条件;#条件是等量关系,故为等值连接
【缺点】:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放到了where后面。SQL:1999【表连接 和 表筛选 分离】#inner可以省略,写的话可读性更好select e.ename,d.dnamefromemp einner joindept done.deptno = d.deptno//条件是等量关系,故为等值连接where筛选条件
【优点】:表连接的条件是独立的,连接之后如果还需要继续筛选,再往后继续添加 where
2.6 内连接:非等值连接

【案例】:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级

【思路】:先看每个表结构,再思考如何选取

mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+
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 |
+--------+---------+-------+
14 rows in set (0.00 sec)
2.7 内连接之自连接

【案例】:查询员工的上级领导,要求显示员工名对应的领导名

【思路】:自己表连接自己表(看作:1个员工表,1个领导表)

select e1.empno '员工编号', e1.ename '员工名', e2.empno '领导编号', e2.ename '领导名'
from emp e1
join emp e2
on e1.mgr = e2.empno;
+----------+--------+----------+--------+
| 员工编号 | 员工名 | 领导编号 | 领导名 |
+----------+--------+----------+--------+
|     7369 | SMITH  |     7902 | FORD   |
|     7499 | ALLEN  |     7698 | BLAKE  |
|     7521 | WARD   |     7698 | BLAKE  |
|     7566 | JONES  |     7839 | KING   |
|     7654 | MARTIN |     7698 | BLAKE  |
|     7698 | BLAKE  |     7839 | KING   |
|     7782 | CLARK  |     7839 | KING   |
|     7788 | SCOTT  |     7566 | JONES  |
|     7844 | TURNER |     7698 | BLAKE  |
|     7876 | ADAMS  |     7788 | SCOTT  |
|     7900 | JAMES  |     7698 | BLAKE  |
|     7902 | FORD   |     7566 | JONES  |
|     7934 | MILLER |     7782 | CLARK  |
+----------+--------+----------+--------+
13 rows in set (0.00 sec)
2.8 外连接:右外连接、左外连接

思考:外连接的查询结果条目一定是 >= 内连接的结果条目:(外连接=内连接+主表没有匹配的行)

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 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)
mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  ||     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
4 rows in set (0.00 sec)

【外连接】:相当于内连接+主表没有匹配的行, outer 可省略,加了可读性好

【right】:将 join 关键字右边的这张表看成主表,主要是为了将这张表中的数据全部都查询出来,捎带着关联查询左边的表。在外连接中,两张表连接产生了主次关系。

【left】:…左边…

任意左连接和右连接可以相互转换

【右外连接】
selecte.ename, d.dname
fromemp e
right outer join dept d
on e.deptno = d.deptno;
+--------+------------+
| ename  | dname      |
+--------+------------+
| MILLER | ACCOUNTING |
| KING   | ACCOUNTING |
| CLARK  | ACCOUNTING |
| FORD   | RESEARCH   |
| ADAMS  | RESEARCH   |
| SCOTT  | RESEARCH   |
| JONES  | RESEARCH   |
| SMITH  | RESEARCH   |
| JAMES  | SALES      |
| TURNER | SALES      |
| BLAKE  | SALES      |
| MARTIN | SALES      |
| WARD   | SALES      |
| ALLEN  | SALES      |
| NULL   | OPERATIONS |
+--------+------------+
15 rows in set (0.00 sec)
【左外连接】
selecte.ename, d.dname
fromemp e
left outer 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.00 sec)

【案例】:查询每个员工的上级领导,要求显示所有员工的名字和领导名

【思路】:相比于外连接,根领导的领导会写null,即查询结果具有14行数据

selecte1.empno '员工编号', e1.ename '员工名', e2.empno '领导编号', e2.ename '领导名'
fromemp e1
left outer joinemp e2
one1.mgr = e2.empno;
+----------+--------+----------+--------+
|  员工编号 |  员工名 |   领导编号 |  领导名 |
+----------+--------+----------+--------+
|     7369 | SMITH  |     7902 | FORD   |
|     7499 | ALLEN  |     7698 | BLAKE  |
|     7521 | WARD   |     7698 | BLAKE  |
|     7566 | JONES  |     7839 | KING   |
|     7654 | MARTIN |     7698 | BLAKE  |
|     7698 | BLAKE  |     7839 | KING   |
|     7782 | CLARK  |     7839 | KING   |
|     7788 | SCOTT  |     7566 | JONES  |
|     7839 | KING   |     NULL | NULL   |
|     7844 | TURNER |     7698 | BLAKE  |
|     7876 | ADAMS  |     7788 | SCOTT  |
|     7900 | JAMES  |     7698 | BLAKE  |
|     7902 | FORD   |     7566 | JONES  |
|     7934 | MILLER |     7782 | CLARK  |
+----------+--------+----------+--------+
14 rows in set (0.00 sec)
2.9 三张表、四张表怎么连接
【语法】一条SQL语句中内连接和外连接可以混合使用
select...
froma
joinb
on  a,b连接条件
joinc
ona和c的连接条件
left joind
ona和d的连接条件
where查询条件;

【案例1】:找出每个员工的部门名称,以及工资等级,要求显示员工名,部门名,薪资,薪资等级

selecte1.ename '员工姓名', e2.dname '部门名', e1.sal '薪资', e3.grade '薪资等级'
fromemp e1
left joindept e2
on e1.deptno = e2.deptno
left joinsalgrade e3
one1.sal between e3.losal and e3.hisal;
+----------+------------+---------+----------+
| 员工姓名 | 部门名     | 薪资    | 薪资等级 |
+----------+------------+---------+----------+
| 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)

【案例2】:找出每个员工的部门名称,工资等级,以及上级领导,要求显示员工名,上级领导名,部门名,薪资,薪资等级

selecte1.ename '员工姓名', e1_1.ename '领导名', e2.dname '部门名', e1.sal '薪资', e3.grade '薪资等级'
fromemp e1
left joinemp e1_1
one1.mgr = e1_1.empno
left joindept e2
on e1.deptno = e2.deptno
left joinsalgrade e3
one1.sal between e3.losal and e3.hisal;
+----------+--------+------------+---------+----------+
| 员工姓名 | 领导名 | 部门名     | 薪资    | 薪资等级 |
+----------+--------+------------+---------+----------+
| SMITH    | FORD   | RESEARCH   |  800.00 |        1 |
| ALLEN    | BLAKE  | SALES      | 1600.00 |        3 |
| WARD     | BLAKE  | SALES      | 1250.00 |        2 |
| JONES    | KING   | RESEARCH   | 2975.00 |        4 |
| MARTIN   | BLAKE  | SALES      | 1250.00 |        2 |
| BLAKE    | KING   | SALES      | 2850.00 |        4 |
| CLARK    | KING   | ACCOUNTING | 2450.00 |        4 |
| SCOTT    | JONES  | RESEARCH   | 3000.00 |        4 |
| KING     | NULL   | ACCOUNTING | 5000.00 |        5 |
| TURNER   | BLAKE  | SALES      | 1500.00 |        3 |
| ADAMS    | SCOTT  | RESEARCH   | 1100.00 |        1 |
| JAMES    | BLAKE  | SALES      |  950.00 |        1 |
| FORD     | JONES  | RESEARCH   | 3000.00 |        4 |
| MILLER   | CLARK  | ACCOUNTING | 1300.00 |        2 |
+----------+--------+------------+---------+----------+
14 rows in set (0.00 sec)

3、子查询

3.1 什么是子查询?
  1. select语句中嵌套select语句,被嵌套的select语句被称为子查询
  2. 子查询一定要在首位加括号
3.2 子查询都可以出现在哪里?
select...(select)...#作为显示,只能逐次输出1个结果
from...(select)...#相当于临时表
where...(select)...#select出的结果当作条件
3.3 where子句中的子查询

【案例】找出比最低工资高的员工姓名和工资?

【思路1】

  1. 查询最低工资是多少

  2. 找出 >800 的

  3. 合并

selectempno, ename, sal
fromemp
wheresal > (select min(sal) from emp);
+-------+--------+---------+
| 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.4 from子句中的子查询

【注意】:from后面的子查询,可以将子查询的结果当作一张临时表

【案例】:找出每个岗位的平均薪资的等级

【思路】

  1. 分组,找出每个岗位的平均工资
  2. 把以上查询结果作为临时表T
  3. 把T表和S表进行表连接
selectt.*, s.grade
from (select job, avg(sal) as avgSal from emp group by job) t
joinsalgrade s
ont.avgSal between s.losal and s.hisal;
+-----------+-------------+-------+
| job       | avgSal      | grade |
+-----------+-------------+-------+
| CLERK     | 1037.500000 |     1 |
| SALESMAN  | 1400.000000 |     2 |
| MANAGER   | 2758.333333 |     4 |
| ANALYST   | 3000.000000 |     4 |
| PRESIDENT | 5000.000000 |     5 |
+-----------+-------------+-------+
3.5 select后面出现的子查询(了解)

【案例】:找出每个员工的部门名称,要求显示员工名、部门名

【思路1】:连接表

【思路2】:子查询语句

【注意】:对于select后面的子查询来说,这个子查询只能一次返回一条结果,多余一条,报错!!!

【思路1】
selecte1.empno, e1.ename, e2.dname
fromemp e1
join dept e2
on e1.deptno = e2.deptno;【思路2】
select e1.empno, e1.ename, (select e2.dname from dept e2 where e1.deptno = e2.deptno) as dname
from emp e1;
+-------+--------+------------+
| empno | ename  | dname      |
+-------+--------+------------+
|  7369 | SMITH  | RESEARCH   |
|  7499 | ALLEN  | SALES      |
|  7521 | WARD   | SALES      |
|  7566 | JONES  | RESEARCH   |
|  7654 | MARTIN | SALES      |
|  7698 | BLAKE  | SALES      |
|  7782 | CLARK  | ACCOUNTING |
|  7788 | SCOTT  | RESEARCH   |
|  7839 | KING   | ACCOUNTING |
|  7844 | TURNER | SALES      |
|  7876 | ADAMS  | RESEARCH   |
|  7900 | JAMES  | SALES      |
|  7902 | FORD   | RESEARCH   |
|  7934 | MILLER | ACCOUNTING |
+-------+--------+------------+

4、union合并查询结果集

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

【思路1】:in, or

【思路2】:union合并(效率更高,why)。对于表连接来说,每连接1次新表,匹配次数满足笛卡尔积,而union可以在减少匹配次数情况下,同时完成两个结果集的拼接。

1.
select empno, ename, job from emp where job in ('manager','salesman');
2.
select empno, ename, job from emp where job = 'manager'
union
select empno, ename, job from emp where job = 'salesman';
+-------+--------+----------+
| empno | ename  | job      |
+-------+--------+----------+
|  7499 | ALLEN  | SALESMAN |
|  7521 | WARD   | SALESMAN |
|  7566 | JONES  | MANAGER  |
|  7654 | MARTIN | SALESMAN |
|  7698 | BLAKE  | MANAGER  |
|  7782 | CLARK  | MANAGER  |
|  7844 | TURNER | SALESMAN |
+-------+--------+----------+
7 rows in set (0.00 sec)

【表连接】:a 连接 b 连接 c

​ a 10条记录

​ b 10条记录

​ c 10条记录

匹配次数是:10*10*10 = 1000

【union合并】:a 连接 b 连接 c

​ a->b 10*10

​ a->c 10*10

匹配次数:10*10+10*10 = 200

【注意事项】:union进行结果集合并时,要求两个结果集的列数和列的数据类型也相同

  1. //报错
    select empno, job from emp where job = 'manager'
    union
    select empno, ename, job from emp where job = 'salesman';
    
  2. //mysql可以通过,但没意义。但是oracle语法严格,不通过,要求数据类型一样,
    select ename, job from emp where job = 'manager'
    union
    select empno, ename from emp where job = 'salesman';
    

5、limit(非常重要)

5.1 limit作用

【提高用户体验】:将查询结果集的一部分取出,通常用于分页查询中。一次全都查出来,用户阅读体验差。

百度:一页显示10条记录

5.2 limit怎么用

【用法】:limit startIndex, length。从0开始

【执行顺序】: mysql中,limit在order by之后执行

【案例1】:按照薪资降序,取出排名在前5的员工

select ename, sal
from emp
order by sal desc
limit 0,5;
mysql> 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 |
+-------+---------+
5 rows in set (0.00 sec)

【案例2】:取出工资排名在[3-5]名的员工

mysql> select ename, sal from emp order by sal desc limit 2,3;
+-------+---------+
| ename | sal     |
+-------+---------+
| FORD  | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+

【案例3】:取出工资排名在[5-9]名的员工?

mysql> 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 |
+--------+---------+
5.3 分页
每页显示3条记录第1页:limit 0,3     [0 1 2]第2页:limit 3,3     [3 4 5]第3页:limit 6,3     [6 7 8]第4页:limit 9,3     [9 10 11]每页显示pageSize条记录第pageNo页:limit (pageNo - 1) * pageSize  , pageSizepublic static void main(String[] args){// 用户提交过来一个页码,以及每页显示的记录条数int pageNo = 5; //第5页int pageSize = 10; //每页显示10条int startIndex = (pageNo - 1) * pageSize;//JDBCString sql = "select ...limit " + startIndex + ", " + pageSize;}

6、DQL语句的大总结

1. 语法顺序
select...
from...
where...
group by...
having...
order by...
limit...2. 执行顺序1. from2. where3. group by4. having5. select6. order by7. limit
3. 去重复distinct
4. 多表联查1. 内连接1. 等值连接2. 非等值连接3. 自连接2. 外连接1. 左外连接(左连接)2. 右外连接(右连接)3.全连接(不讲)
5. 子查询
6. union合并查询结果
7. limit

-------------------------------------------------------------DDL------------------------------------------------------------------

7、表的创建(建表)

7.1 建表的语法格式:(DDL语句,包括:create, drop, alter)
create table 表名(字段名1 数据类型, 字段名2 数据类型, 字段名3 数据类型);create table 表名(字段名1 数据类型(length), 字段名2 数据类型(length), ...字段名n 数据类型(length));

【表名】:建议以t_或者tbl_开始,可读性强。见名知意。

【字段名】:见名知意

表名和字段名都属于标识符

7.2 关于mysql中的数据类型

有很多,我们只需要掌握常见的数据类型即可。

varchar(最长255)

  1. 声明最大长度,存储可变长度的字符串,会根据实际的数据长度动态分配空间
  2. 比较智能,节省空间

【优点】:节省空间

【缺点】:需要动态分配空间,速度慢

char

  1. 定长字符串
  2. 不管实际的数据长度是多少,分配固定长度的空间取存储数据
  3. 使用不恰当时,可能会导致空间的浪费

【优点】:不需要动态分配空间

【缺点】:使用不当可能会导致空间的浪费

性别字段选用char,因为固定长度

int(最长11)

​ 1. 数字中的整数型。等同于java中的int

bigint

  1. 数字中的长整型。等同于java中的long

float

  1. 单精度浮点型数据

double

  1. 双精度浮点型数据

date

  1. 短日期类型

datetime

  1. 长日期类型

clob

  1. 字符大对象,最多可存储4G的字符串
  2. 比如:存储一篇文章,一个说明
  3. 超过255个字符的都要采用CLOB字符大对象来存储
  4. Chracter Large Object: CLOB

blob

  1. 二进制大对象
  2. Binary Large Object: BLOB
  3. 专门用来存储图片、声音、视频等流媒体数据
  4. 网BLOB类型的字段上插入数据的时候,例如插入一个图片、视频等,需要用IO流

【案例】t_moive 电影表 (专门存储电影信息的)

编号 姓名 故事情节 上映日期 时长 海报 类型
no(bigint) name(varchar) discription(clob) playtime(date) time(double) image(blob) type(char)
1000
7.3 创建一个学生表?

括号内的只是建议长度,超过也不会报错,char:1文字1长度

学号、姓名、年龄、性别、邮箱地址

create table t_student4_4(student_id int,student_name varchar(255),sex char(6),age int(3),email varchar(255)
);

删除表

drop table if exists t_student4_4;
7.4 插入数据insert ( DML )

【注意】: insert 只要执行成功,就会多一行记录。没有指定默认值的字段,默认值为null。

语法格式:insert into 表名(字段名1, 字段名2, 字段名3, ...) values(值1, 值2, 值3, ...);
【注意】:
1. 字段名和值,要一一对应
2. 前面的字段名省略的话,等于都写上了!所以值也要【全都】写上!!并且【不能颠倒顺序】!!
3. insert 只要执行成功,就会多一行记录。没有【指定默认值】的字段,默认值为null。
drop table if exists t_student4_4;
create table t_student4_4(student_id int,student_name varchar(255),sex char(6),age int(3),email varchar(255),测试 varchar(255) default '没输入'
);
insert into t_student4_4 values(001, 'Kate', 'f', 17, 'Kate@edu.csu.cn', '输入了');
insert into t_student4_4(student_id, student_name, sex, age, email) values(002, 'Jack', 'm', 17, 'Jack@edu.csu.cn');
select * from t_student4_4;
7.5 insert插入日期

数字格式化:format(数字, ‘格式’)

1. 查询员工薪水加入千分位
select ename,format(sal, 0) as sal from emp;
2. 查询员工薪水加入千分位和保留两位小数
select ename, format(sal, 2) as sal from emp;

str_to_date 将字符串varchar类型转换成date类型

通常用于insert语句,因为需要将date->varchar

drop table if exists t_student4_4;
create table t_student4_4(id int,姓名 varchar(255),生日 char(10)#可以用data类型  #生日 date
);
mysql> desc t_student4_4;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | YES  |     | NULL    |       |
| 姓名   | varchar(255) | YES  |     | NULL    |       |
| 生日   | char(10)     | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
插入数据?
insert into t_student4_4(id, 姓名, 生日) values(1, 'jack', '01-10-2001');

【命名规范】:所有标识符都是小写,用下划线衔接

insert into t_student4_4(id, 姓名, 生日) values(1, 'jack', str_to_date('01-10-2001', '%d-%m-%Y'));
【注意】:如果是'%Y-%m-%d'形式,无需 str_to_date
insert into t_student4_4(id, 姓名, 生日) values(1, 'jack', '2001-02-11');

mysql日期格式,对大小写敏感

%Y 年【记住这里是大写】

%m 月

%d 日

%h 时

%i 分

%s 秒

date_format :将date类型转换成具有一定格式的varchar字符串类型

【用法】:date_format(日期类型数据, ‘日期格式’);

通常用于查询日期时,修改展示的日期格式。不指定的话,mysql会默认指定为:‘%Y-%m-%d’ 形式

mysql> select id, 姓名 'name', date_format(生日,'%Y年%m月%d日') as birth from t_student4_4;
+------+------+----------------+
| id   | name | birth          |
+------+------+----------------+
|    1 | jack | 2001年10月01日 |
|    1 | jack | 2001年02月11日 |
+------+------+----------------+mysql> select id, 姓名 'name', 生日 as birth from t_student4_4;#默认形式
+------+------+------------+
| id   | name | birth      |
+------+------+------------+
|    1 | jack | 2001-10-01 |
|    1 | jack | 2001-02-11 |
+------+------+------------+
7.6 date和datetime两个类型的区别

date:短日期,只包括年月日信息

datetime:是长日期,包括年月日时分秒信息

drop table if exists t_user;
create table t_user(id int,name varchar(32),birth date,create_time datetime
);
id 是整数
name 是字符串
birth 是短日期
create_time 是这条记录的创建时间:长日期类型

mysql短日期默认格式:%Y-%m-%d

mysql长日期默认格式:%Y-%m-%d %h: %i: %s

insert into t_user(id,name,birth,create_time) values(1,'zhangsan','1990-10-01','2020-03-18 15:49:50');

mysql通过now() 函数获取系统当前时间,并且获取的时间带有:时分秒信息!!!!是datetime类型的。

insert into t_user(id,name,birth,create_time) values(2,'lisi','1991-10-01',now());
+------+----------+------------+---------------------+
| id   | name     | birth      | create_time         |
+------+----------+------------+---------------------+
|    1 | zhangsan | 1990-10-01 | 2020-03-18 15:49:50 |
|    2 | lisi     | 1991-10-01 | 2022-04-04 22:13:26 |
|    3 | wangwu   | 1991-10-01 | 2022-04-04 22:14:42 |
+------+----------+------------+---------------------+
7.7 update ( DML )
语法格式:
update 表名 set 字段名1 = 值1, 字段名2 = 值2, 字段名3 = 值3... where 条件;
【注意】:没有条件会导致所有数据全部更新,所以条件要确定行【如,主键】
update t_user set name = 'jack' where id = 2;
+------+----------+------------+---------------------+
| id   | name     | birth      | create_time         |
+------+----------+------------+---------------------+
|    1 | zhangsan | 1990-10-01 | 2020-03-18 15:49:50 |
|    2 | jack     | 1991-10-01 | 2022-04-04 22:13:26 |
|    3 | wangwu   | 1991-10-01 | 2022-04-04 22:14:42 |
+------+----------+------------+---------------------+
3 rows in set (0.00 sec)
update t_user set birth = '2002-02-26', create_time = now() where id = 2;
mysql> select * from t_user;
+------+----------+------------+---------------------+
| id   | name     | birth      | create_time         |
+------+----------+------------+---------------------+
|    1 | zhangsan | 1990-10-01 | 2020-03-18 15:49:50 |
|    2 | jack     | 2002-02-26 | 2022-04-04 22:24:33 |
|    3 | wangwu   | 1991-10-01 | 2022-04-04 22:14:42 |
+------+----------+------------+---------------------+
update t_user set create_time = now();
mysql> select * from t_user;
+------+----------+------------+---------------------+
| id   | name     | birth      | create_time         |
+------+----------+------------+---------------------+
|    1 | zhangsan | 1990-10-01 | 2022-04-04 22:25:08 |
|    2 | jack     | 1991-10-01 | 2022-04-04 22:25:08 |
|    3 | wangwu   | 1991-10-01 | 2022-04-04 22:25:08 |
+------+----------+------------+---------------------+
7.8 delete(DML)
语法格式:
delete from 表名 where 条件;
【注意】:没有条件,整表全部删除
delete from t_user where id = 2;mysql> select * from t_user;
+------+----------+------------+---------------------+
| id   | name     | birth      | create_time         |
+------+----------+------------+---------------------+
|    1 | zhangsan | 1990-10-01 | 2022-04-04 22:25:08 |
|    3 | wangwu   | 1991-10-01 | 2022-04-04 22:25:08 |
+------+----------+------------+---------------------+
2 rows in set (0.00 sec)insert into t_user(id) values(2);
delete from t_user;#删除所有内容mysql> select * from t_user;
Empty set (0.01 sec)drop table if exists t_user;#drop是删除整个表结构

CRUD操作(create 添加数据read读取数据 update 修改数据delete删除数据)

三、Day 03

1、查询每个员工的所在部门名称?要求显示员工名和部门名?

连接并不能提高效率,只是筛选出符合条件的有效数据。
别名能够提高效率加条件只是为了避免笛卡尔积现象,只是为了查询出有效的组合记录。
匹配的次数一次都没有少,还是56次。selecte.ename, d.dname
fromemp e
joindept d
one.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.01 sec)

2、insert语句可以一次插入多条记录【掌握】

【语法】:
insert into 表名(字段名1, 字段名2) values(值1, 值2),(值1, 值2),(值1, 值2);insert into t_user(id, name, birth, create_time) values(1,'zs','1980-10-11',now()), (2,'lisi','1981-10-11',now()),(3,'wangwu','1982-10-11',now());

3、快速建表

【原理】:

  1. 将一个查询结果当做一张表新建!!!!!
  2. 这个可以完成表的快速复制!!!!
  3. 表创建出来,同时表中的数据也存在了!!!
create table mytable as select empno, ename from emp where job = 'manager';drop table if exists t_user;#drop是删除整个表结构

4、将查询结果插入到一张表中?insert相关

#结果和表的结构(字段个数和数据类型)要对应
insert into mytable (select * from mytable);#用的比较少

5、快速删除表中的数据?【truncate比较重要,必须掌握,DDL操作】

【用法】:

truncate table dept_bak; #这种操作属于DDL操作

【注意】:使用truncate之前,必须仔细询问客户是否真的要删除,并警告删除之后不可恢复!

  1. delete原理:

    ​ 表中数据被删除了,但是数据在硬盘中的真实存储空间不会被释放!

    1. 缺点:删除效率低
    2. 优点:可以回滚数据
delete from mytable where empno = 7566;
  1. truncate原理:

    ​ 表被一次性截断,物理删除!

             a. 缺点:不支持回滚
    

    ​ b. 优点:快速,效率高

大表,包含上亿条记录????
使用 delete,也许需要执行1个小时才能删除完!效率较低。
使用 truncate,只需要不到1秒钟的时间就删除结束。效率较高。
truncate是删除表中的数据,表还在!

  1. 与drop区别:
drop table 表名; # 这不是删除表中的数据,这是把表删除。

6、对表结构的增删改?【DDL,create drop alter,针对字段】

  1. 什么是对表结构的修改?alter

添加一个字段、删除一个字段、修改一个字段

#添加字段[默认字段于尾,可设置首,及任意位置。可添加默认值。comment里为备注信息]
alter table 表名 add 新字段名 数据类型[(长度)];
alter table 表名 add 字段名 varchar(255) first;
alter table 表名 add 字段名 varchar(255) default null comment '申请详情';
alter table 表名 add 字段名 decimal(10,2) DEFAULT '0.00' comment '抵扣消费金额' after 字段名(在其后插入新字段);
#修改数据类型/长度
alter table 表名 modify 旧字段名 数据类型;
#修改字段名
alter table 表名 change 旧字段名 新字段名 数据类型;
#删除字段
alter table 表名 drop 字段名;

【测试】:快速建表,然后修改字段

#删除整个表结构mytable
drop table if exists mytable;
#根据select查询结果快速创建表mytable
create table mytable as (select e.deptno, e.empno, e.ename, e.sal, job, d.loc from emp e join dept d on e.deptno = d.deptno);
#显示表结构和表内容
desc mytable;
select * from mytable;
#新增字段gender
alter table mytable add gender int;
#设置新增gender所有内容为1
update mytable set gender = 1;
#显示表结构和表内容
select * from mytable;
desc mytable;
#把所有列显示为小写
update mytable set ename = lower(ename), loc = lower(loc), job = lower(job);
#把所有列都显示为大写
update mytable set ename = upper(ename), loc = upper(loc), job = upper(job);
#把gender字段改为sex字段
alter table mytable change gender sex int;
#删除新增的sex字段
alter table mytable drop sex;
#在第一列新增字段:number, not null表示字段值不能为空
alter table mytable add number int not null comment '测试序号' first;
#在序号后新增字段:university
alter table mytable add university varchar(10) default 'CSU' after number;
#显示表结构和表内容
desc mytable;
select * from mytable;
  1. 对表修改的修改使用:alter

属于DDL语句

  1. DDL包括:create、drop、alter

第一:在实际开发中,需求一旦确定后,表一旦设计好,很少进行表结构的修改。因为开发过程中,修改表结构,成本较高。修改表结构之后,对应的java代码就需要进行大量的修改。

第二:修改表结构的操作较少,如果需要修改表结构,使用工具

第三:修改表结构的操作不需要写道java程序中,实际上也不是java程序员的范畴。

7、约束(极其重要*****)

7.1 什么是约束?
  1. 约束对应的英语单词:constraint
  2. 在创建表的时候,我们可以给表的字段加上一些约束,来保证这个表数据的完整性、有效性。
  3. 约束的作用:保证表中的数据有效!!!
  4. 只是约束,对字段删除/增加约束,不会增加/减少字段
7.2 约束包括哪些?
  • 非空约束:not null
  • 唯一性约束:unique
  • 主键约束:primary key(PK)
  • 外键约束:foreign key(FK)
  • 检查约束:check key(mysql不支持,orcale支持)
7.3 非空约束:not null
  1. 非空约束not null约束的字段不能为null

    1. 列级约束
drop table if exists t_vip;
create table t_vip(id int,name varchar(255) not null  // not null只有列级约束,没有表级约束!
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');insert into t_vip(id) values(3);
ERROR 1364 (HY000): Field 'name' doesn't have a default value
7.4 唯一性约束:unique
  1. 唯一性约束unique约束的字段不能重复,但是可以为null

    1. 列级约束
    2. 表级约束:需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束。
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,'zhangsan','zhangsan@123.com');insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');select * from t_vip;insert into t_vip(id,name,email) values(4,'wangwu','wangwu@sina.com');ERROR 1062 (23000): Duplicate entry 'wangwu' for key 'name'
#name字段虽然被unique约束了,但是可以为NULL。insert into t_vip(id) values(4);insert into t_vip(id) values(5);
  1. 两个字段联合起来具有唯一性
# 1. 如下不符合,因为这代表各自唯一,不是联合
drop table if exists t_vip;
create table t_vip(id int,#约束直接添加到列后面的,叫做【列级约束】。name varchar(255) unique,email varchar(255) unique#但如果采用以上方式创建表的话,肯定创建失败,因为'zhangsan'和'zhangsan'重复了。insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');
);
# 2. 应该这样创建
drop table if exists t_vip;
create table t_vip(id int,name varchar(255) unique not null,email varchar(255) unique not null,#约束没有添加在列的后面,这种约束被称为【表级约束】。unique(name,email)
);insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');select * from t_vip;
  1. unique和null联合

    1. 在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段(非空且不重复,当然是主键特征)。多个字段被同时声明not null unique,则第一个为主键。

      drop table if exists t_vip;
      create table t_vip(id int,name varchar(255) unique not null,email varchar(255) unique not null,#约束没有添加在列的后面,这种约束被称为【表级约束】。unique(name,email)
      );
      Query OK, 0 rows affected (0.06 sec)mysql> desc t_vip;
      +-------+--------------+------+-----+---------+-------+
      | Field | Type         | Null | Key | Default | Extra |
      +-------+--------------+------+-----+---------+-------+
      | id    | int          | YES  |     | NULL    |       |
      | name  | varchar(255) | NO   | PRI | NULL    |       |
      | email | varchar(255) | NO   | UNI | NULL    |       |
      +-------+--------------+------+-----+---------+-------+
      3 rows in set (0.00 sec)
      
    2. 【注意】:oracle中不一样!

7.5 主键约束(Primary key, PK,非常重要*****)
  1. PK的相关术语:

    1. 主键约束:就是一种约束
    2. 主键字段:该字段上添加了主键约束,这样的字段叫:主键字段
    3. 主键值:主键字段中的每个值都叫做:主键值
  2. 什么是主键?作用?

    1. 主键值是每一行记录的唯一标识
    2. 任何表都应该有主键,否则是无效表
  3. 主键特征

    1. not null+unique,非空且不重复
  4. 给表添加主键约束

    1. 列级约束
    2. 表级约束:复合主键(联合主键)
    3. 建议单一主键,不建议复合主键
    4. 结论:一张表,主键约束只能添加1个。(主键只能有1个)
  5. 主键值建议类型:

    1. int
    2. bigint
    3. char
    4. 主键值通常是递增的数字,一般是定长,不建议使用varchar
  6. 主键分类2种

    1. 单一主键

    2. 复合主键

    3. 自然主键:主键值是一个自然数,和业务没关系

    4. 业务主键:主键值和业务紧密关联,例如拿银行卡账号作主键值。

      • 自然主键使用较多,因为不需要意义,只要不重复即可。如果与业务挂钩,则业务发生变动时,可能会影响主键值。
  7. MySQL自动维护主键值

    1. 创建表时,可以使用 auto_increment 表示自增,从1开始,以1递增

      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
      ('jack'),
      ('jack'),
      ('jack'),
      ('jack');
      
    2. 已存在的表,添加主键约束

      alter table 表名 modify 列名 数据类型 primary key;alter table 表名 add primary key(列名);alter table 表名 add constraint 主键约束的名字(自定义) primary key(列名);
      

​ 3. 删除递增主键约束时,要先去掉递增属性

#递增主键字段id改为普通int
alter table 表名 modify 字段名 int;
#删除普通主键约束(只有一个主键,不用指定字段)
alter table 表名 drop primary key;

【代码测试】

drop table if exists t_vip;
#1个字段做主键,叫做:单一主键
create table t_vip(id int primary key,  #列级约束name varchar(255)
);
insert into t_vip(id,name) values(1,'zhangsan'),values(2,'lisi');#错误:不能重复
insert into t_vip(id,name) values(2,'wangwu');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'#错误:不能为NULL
insert into t_vip(name) values('zhaoliu');
ERROR 1364 (HY000): Field 'id' doesn't have a default value#可以使用表级约束 添加约束
drop table if exists t_vip;create table t_vip(id int,name varchar(255),primary key(id)  #表级约束);insert into t_vip(id,name) values(1,'zhangsan');#错误insert into t_vip(id,name) values(1,'lisi');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'   #表级约束主要是给多个字段联合起来添加约束,
#id和name联合起来做主键:复合主键!!!!
drop table if exists t_vip;create table t_vip(id int,   name varchar(255),email varchar(255),primary key(id,name)
);insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');#错误:不能重复insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');ERROR 1062 (23000): Duplicate entry '1-lisi' for key 'PRIMARY'#一个表中主键约束能加两个吗?不,有且仅有1个drop table if exists t_vip;create table t_vip(id int primary key,name varchar(255) primary key);
#ERROR 1068 (42000): Multiple primary key defined
7.6 外键约束(foreign key, PK, 非常重要)
  1. 相关术语

    1. 外键约束:一种约束:foreign key
    2. 外键字段:该字段被添加了外键约束
    3. 外键值:主键字段当中的每一个值
  2. 外键不一定是主表的主键,但是一定要具有唯一性unique约束,添加外键后,外键值可以为空

  3. 业务背景

  • 设计数据库表,描述班级和学生信息

【方案1】:班级和学生存储在一张表

no(PK) name classno classname
1 jack 100 北京市大兴区亦庄镇第二中学高三1班
2 luck 100 北京市大兴区亦庄镇第二中学高三1班
3 rose 101 北京市大兴区亦庄镇第二中学高三2班
4 bourne 101 北京市大兴区亦庄镇第二中学高三2班
  • 缺点:数据冗余、空间浪费
  • 评价:设计比较失败

【方案2】:班级表、学生表

classno(pk) classname
100 北京市大兴区亦庄镇第二中学高三1班
101 北京市大兴区亦庄镇第二中学高三2班
no(pk) name csno
1 jack 100
2 luck 100
3 rose 101
4 bourne 101
  • 当csno没有任何约束的时候,可能导致数据无效(102不在班级表中)

    为了保证cno字段中的值都是100和101,需要给cnoi段添加外键约束

    【注意】:如果classno不具有唯一性,那么就无法得知csno所属了

【故】:csno就是外键字段,csno字段中每一个值都是外键值。

【注意】:t_class是父表(被引用的表)

​ t_student是子表(添加外键的表)

drop table if exists t_class;
drop table if exists t_students;
#因为希望有外键,故先创建父表,再子表
create table t_class(classno int primary key,classname varchar(255)
);
create table t_students(no int primary key auto_increment,#主键自增name varchar(255),csno int,#【添加外键约束】foreign key(csno) references t_class(classno)
);insert into t_class(class, classname) values(100, '北京市大兴区亦庄镇第二中学高三1班');
insert into t_class(class, classname) values(101, '北京市大兴区亦庄镇第二中学高三2班');insert into t_students(name, csno) values
('jack', 100),
('lucy', 100),
('rose', 101),
('bourne', 101);
insert into t_students(name) values ('kate');#报错
insert into (csno) values(102);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`bjpowernode`.`t_students`, CONSTRAINT `t_students_ibfk_1` FOREIGN KEY (`csno`) REFERENCES `t_class` (`classno`))
  1. 创建外键【约束】的两种方式

    1. 创建表时直接创建外键约束
  • 备注:必须先创建参照表,才能在创建外键约束,即必须现有表Category,再有book

  • foreign key(子表字段) references 父表名(父表字段);
    #删除外键字段
    alter table 表名 drop foreign key 外键约束的名字;
    
    1. 先创建表,表创建成功后,单独添加外键约束
  • alter table 子表名 add constraint 外键约束的名字(自定义) foreign key(字段1) references 主表名(字段2);
    

【测试】

create table books(bookid number(10) not null primary key,bookName varchar2(20) not null,price number(10,2),categoryId number(10) not null
);
ALTER TABLE books ADD CONSTRAINT FK_Book_categoryid FOREIGN KEY(categoryId ) REFERENCES Category(id);

create table t_students(no int primary key auto_increment,#主键自增name varchar(255) not null,csno int not null default 100,#【添加外键约束】foreign key(csno) references t_class(classno)
);#删除外键约束【只是删除约束,并没有删除字段】
alter table t_students drop foreign key class_id;
alter table t_students add class_id int default 100 after name;
#如下【constaint关键字一定要在】
alter table t_students add constraint class_id foreign key(class_id) references t_class(classno);
  1. 主表和子表的创建和删除具有顺序

    • 依照他们的时间周期
7.7 级联更新与级联删除
  1. 级联更新 on update cascade

    1. 先删除子表的外键约束
    2. 然后同时添加外键约束和级联更新
    3. 这样,当更新父表被引用的字段时,子表会被自动更新
alter table t_students drop foreign key fk_class_id;alter table t_students add constraint fk_class_id foreign key(class_id) references t_class(classno) on update cascade;#要保证所有没有被设置级联更新的外键都被删除了
update t_class set classno = 20 where classno = 101;
  1. 级联删除 on delete cascade

    1. 先删除子表的外键约束
    2. 然后同时添加外键约束和级联删除
    3. 这样,当删除父表被引用的字段时,子表会被自动删除
alter table t_students drop foreign key fk_class_id;alter table t_students add constraint fk_class_id foreign key(class_id) references t_class(classno) on delete cascade;
#只删除父表中数据,但是子表中的数据也会被删除
delete from t_class where classno = 100;
7.8 删除约束
1. alter table 子表名 drop foreign key 外键约束名;
2. alter table 子表名 drop primary key 主键约束名;
3. alter table 子表名 drop key 约束名;
7.9 添加约束
1. alter table 子表名 add constraint 外键约束名 foreign key(子表字段) references 父表名(父表字段);
2. alter table 子表名 add constraint 外键约束名 primary key(字段);
7.10 修改约束
alter table 表名 modify 字段名 类型 约束;

8、存储引擎

8.1 存储引擎的作用
#看表的详细信息:存储引擎、结构、约束等
show create table 表名;mysql> show create table t_students;
+------------+--------------------------------------------------------------
| Table      | Create Table
| t_students | CREATE TABLE `t_students` (`no` int NOT NULL,`name` varchar(255) DEFAULT NULL,`class_id` int DEFAULT '100',`csno` int DEFAULT NULL,PRIMARY KEY (`no`),KEY `fk_csno` (`csno`),KEY `fk_class_id` (`class_id`),CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `t_class` (`classno`),CONSTRAINT `fk_csno` FOREIGN KEY (`csno`) REFERENCES `t_class` (`classno`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+------------+--------------------------------------------------------------
  1. 存储引擎是MySQL中特有的一个术语,其他数据库中没有。

    • Oracle中有,但是不叫这个名字
  2. 存储引擎是存储/组织数据的方式
  3. 不同的存储引擎,存储数据的方式不同
8.2 给表添加/指定“存储引擎”
  1. 查看表的详细信息:存储引擎、结构、约束…
1. show create table 表名;
2. show table status '表名';
  1. 建表时使用关键字ENGINE显示指定存储引擎
 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` (`classno`)) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
  1. 对现有表使用alter table语句改变存储引擎
alter table 表名 engine = innodb;
8.3 查看mysql支持的存储引擎
  1. 查看mysql版本
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.28    |
+-----------+
  1. 查看支持引擎
mysql> show engines\G
*************************** 1. row ***************************Engine: MEMORYSupport: YESComment: Hash based, stored in memory, useful for temporary tables
Transactions: NOXA: NOSavepoints: NO
*************************** 2. row ***************************Engine: MRG_MYISAMSupport: YESComment: Collection of identical MyISAM tables
Transactions: NOXA: NOSavepoints: NO
*************************** 3. row ***************************Engine: CSVSupport: YESComment: CSV storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 4. row ***************************Engine: FEDERATEDSupport: NOComment: Federated MySQL storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 5. row ***************************Engine: PERFORMANCE_SCHEMASupport: YESComment: Performance Schema
Transactions: NOXA: NOSavepoints: NO
*************************** 6. row ***************************Engine: MyISAMSupport: YESComment: MyISAM storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 7. row ***************************Engine: InnoDBSupport: DEFAULTComment: Supports transactions, row-level locking, and foreign keys
Transactions: YESXA: YESSavepoints: YES
*************************** 8. row ***************************Engine: BLACKHOLESupport: YESComment: /dev/null storage engine (anything you write to it disappears)
Transactions: NOXA: NOSavepoints: NO
*************************** 9. row ***************************Engine: ARCHIVESupport: YESComment: Archive storage engine
Transactions: NOXA: NOSavepoints: NO
9 rows in set (0.00 sec)
8.4 mysql常用存储引擎

【主键】:对于一张表,主要是主键,或者加有unique约束的字段上会自动创建索引

  1. MyISAM存储引擎

    1. 最常用的存储引擎
    2. 具有如下特征:
      1. 使用三个文件表示每个表

        1. 格式文件-存储表结构的定义(mytable.frm)
        2. 数据文件-存储表行的内容(mytable.myd)
        3. 索引文件-存储表上的索引(mytable.myi)
      2. 灵活的auto-increment字段处理
      3. 【优势】可被转换为压缩、只读表来节省空间
      4. MyISAM不支持事务机制,安全性低
      5. 全表锁
  2. InnoDB存储引擎

    1. MySQL默认采用InnoDB存储引擎,是重量级的存储引擎(行锁)
    2. innodb支持事务,支持数据库崩溃后自动恢复机制
    3. 主要特点是十分安全
    4. 具有如下特征:
      1. 每个innodb表在数据库目录中以.frm格式文件表示
      2. 用commit(提交)、savepoint及rollback(回滚)支持事务处理
      3. 提供ACID兼容
      4. 在mysql服务器崩溃后,可提供自动恢复
      5. 多版本(MVCC)和行级锁定
      6. 支持外键及引用的完整性,包括级联删除和更新
    5. 主要特点:
      1. 支持事务,以保证数据的安全性
      2. 效率不是很高,不能压缩,不能转换为只读,不能很好的节省磁盘空间
  3. memory存储引擎

    1. 【速度快】使用memory存储引擎的表,数据存储在内存中,且行的长度固定
    2. 具有如下特征:
      1. 在数据库目录内,每个表均以.frm格式的文件表示
      2. 表数据及索引被存储在内存中(目的就是快)
      3. 表级锁
      4. 不能包含TEXT或者BLOB字段
    3. 以前被称作heap引擎
    4. 主要特点:
      1. 查询效率是最高的,不需要和硬盘交互
      2. 不安全,关机之后数据消失,因为数据和索引都是在内存中

9、事务(非常重要*****)

9.1 什么是事务

​ 事务就是一组DML语句对数据库进行操作,它们要么全部完成,要么全部不完成,具有ACID性质:

9.2 什么sql语句支持事务
  1. 只有以下三个DML语句才会有事务,其他语句与事务无关

    1. insert
    2. delete
    3. update
  2. 因为以上三个数据对数据库表中数据进行增、删、改,涉及到了安全问题,故引入事务。

9.3 事务存在的意义
  1. 因为所有的业务不可能一条DML语句就能完成,多条DML涉及到安全问题,故必须引入事务。

  2. 一个事务其实就是多条DML语句同时成功,或者同时失败。

9.4 事务的原理
1. InnoDB存储引擎:提供了一组用来记录事务性活动的日志文件
 事务开启了:insertinsertinsertdeleteupdateupdateupdate事务结束了!

在事务执行过程中,每一条DML操作都会记录到“事务性活动的日志文件“中;在事务的执行过程中,我们可以提交事务,也可以回滚事务。

  1. 提交事务

  2. 清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中

  3. 提交事务标志着:事务结束,并且是一种全部成功的结束。

  4. 回滚事务

    1. 将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件
    2. 回滚事务标志着:事务的结束,并且是一种全部失败的结束。
9.5 如何提交事务,如何回滚事务
  1. 提交事务:commit语句
  2. 回滚事务:rollback语句(永远只能回滚到上一次的提交点)

【transaction:事务】

  1. mysql中默认自动提交事务

    1. 每执行一条DML语句,就提交一次
    2. 并不符合我们的开发习惯,因为我们通常需要多条DML语句作为一个业务,同时成功后才能提交,而不能
  2. 自定义事务提交

    1. 先开启事务:

      start transaction
      
    2. 执行事务操作

【回滚】:演示事务回滚

create table dept_bak(no int, name varchar(255), hometown varchar(255));
start transaction;
insert into dept_bak values(10,'abc', 'bj');
insert into dept_bak values(20,'abc', 'tj');
select *
from dept_bak;
rollback;
select *
from dept_bak;

【提交】:演示事务提交

start transaction;
insert into dept_bak values(10,'abc','bj');
insert into dept_bak values(20,'abc','tj');
commit;
select * from dept_bak;
9.6 事务的ACID性质

原子性(atomicty)

事务是最小的工作单元,不可再分,要么全部提交,要么全部回滚,没有中间状态

一致性(consistency)

事务执行前后,数据从一个合法性状态变换成另一个合法性状态,这种状态是语义上的(满足预定的约束状态),不是语法上的。

隔离性(Isolation)

一个事务的执行,不能被其它事务,即一个事务内部的操作及其使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能相互干扰(资源互斥)

持久性(durability)

一个事务一旦被提交,他对数据库中的数据的改变就是永久性的(通过重做日志和回滚日志实现)。事务提交:将没有保存到硬盘上的数据保存到硬盘上。

【原子性是基础,隔离性是手段,一致性是约束条件,持久性则是我们的目的】

9.7 事务的5种状态

活动的:事务对应的数据库操作正在执行

部分提交的:事务中的最后一个操作完成,但是操作都在内存中,还没有把结果刷新到磁盘中

失败的:处于活动的,或者部分提交时出现了错误

中止的:执行了一部分而变为失败的,就需要把已经修改的事务的操作还原到执行之前,这个回滚操作完成后,数据库恢复到了执行事务之前的状态,我们就说该事务处于中止

提交的:修改过的数据都同步到了磁盘

9.7 事务隔离级别
  1. 数据并发问题

    (不保证串行):【数据不一致】
    **1. 脏写:**事务A修改了另一个未提交事务B修改过(可能会回滚)的数据,就发生了脏写(提交了的数据被回滚掉了,即数据没有变化)
    **2. 脏读:**事务A读取了B更新但没有被提交的字段(若B回滚了,则A读取的内容是临时且无效的)
    3. 不可重复读:A读取了一个字段,然后B更新了该字段,则A再次读取同一个字段,值就不同了
    4. 幻读(多读:读到了之前没读到的记录):A从一个表读取了一个字段,B插入了新行(幻影记录),A再读就多了几行

    • 四种隔离级别(都解决了脏写):都解决了,并发性特别差,先给问题严重性排序:
      • 脏写>脏读>不可重复读>幻读
  2. 四个隔离级别(逐渐加强)

    我们愿意舍弃一部分隔离性来换取一部分性能:设立4个隔离级别,越低则并发问题发生越多,越往下并发越差
    1. READ UNCOMMITTED:读未提交,允许一个事务读其他事务未提交的字段,有脏读可能
    2. READ COMMITTED:读已提交(oracle默认),一个事务只能读其他事务已提交的字段,有不可能脏读
    3. REPEATABLE READ:可重复读(mysql默认),确保如果在一个事务中多次执行相同的select语句,都能得到相同的结果,不管其他事务是否提交修改(银行转账)。
    4. SERIALIZABLE:可串行化,效率最低,事务排队,不能并发。synchronized,线程同步(事务同步)。

隔离级别 脏读可能 不可重复读可能 幻读可能性 加锁读
读未提交 yes yes yes no
读已提交 no yes yes no
可重复读 no no InnoDB解决了 no
可串行化 no no no yes
9.8 验证各种隔离级别
#设置全局隔离级别
set global transaction isolation level read uncommitted;
#- read-uncommitted
#- read-committed
#- repeatable-read
#- serializable#退出后重进,查看隔离级别
sql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)
#打开两个mysql端,进行事务的隔离级别验证
9.9 设置服务器的缺省隔离级别
  1. 通过修改配置文件设置

    • 可以在my.ini文件中使用transaction-isolation选项来设置服务器的缺省事务隔离级别

      • read-uncommitted
      • read-committed
      • repeatable-read
      • serializable
    • - [mysqld]
      - transaction-isolation = read-committed
      
  2. 通过动态命令设置隔离级别

    • #设置全局隔离级别,要退出后重进,才修改了隔离级别
      set global transaction isolation level read uncommitted;
      #global -> session则是仅改变当前会话的隔离级别,不用退出重进
      set session transaction isolation level read uncommitted;
      #查看事务隔离级别
      sql> select @@transaction_isolation;
      +-------------------------+
      | @@transaction_isolation |
      +-------------------------+
      | read uncommitted        |
      +-------------------------+
      1 row in set (0.00 sec)
      
      • read uncommitted
      • read committed
      • repeatable read
      • serializable

三、Day 04

1、索引

1.1 什么是索引

MySQL在查询方面主要就是两种方式:
第一种方式:全表扫描
第二种方式:根据索引检索。

​ 索引【自主添加】是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。一张表的一个字段可以添加一个索引,多个字段联合起来也可以添加索引。

​ 索引相当于一本书的目录,是为了缩小扫描范围而存在的机制。

​ 对于一本字典来说,查找某个汉字有两种方式:
​ 第一种方式:一页一页挨着找,直到找到为止,这种查找方式属于全字典扫描。
​ 效率比较低。
​ 第二种方式:先通过目录(索引)去定位一个大概的位置,然后直接定位到这个
​ 位置,做局域性扫描,缩小扫描的范围,快速的查找。这种查找方式属于通过
​ 索引检索,效率较高。

select * from t_user where name = ‘jack’;

以上的这条SQL语句会去name字段上扫描,为什么?
因为查询条件是:name=‘jack’

如果name字段上没有添加索引,或者说没有给name字段创建索引,
MySQL会进行全扫描,会将name字段上的每一个值都比对一遍。效率比较低。

【注意】:
在实际中,汉语字典前面的目录是排序的,按照a b c d e f…排序,
为什么排序呢?因为只有排序了才会有区间查找这一说!(缩小扫描范围
其实就是扫描某个区间罢了!)

在mysql数据库当中索引也是需要排序的,并且这个所以的排序和TreeSet
数据结构相同。TreeSet(TreeMap)底层是一个自平衡的二叉树!在mysql
当中索引是一个B-Tree数据结构。

​ 遵循左小右大原则存放。采用中序遍历方式遍历取数据。

1.2 索引的实现原理

假设有一张用户表:t_user

id(PK)                   name            每一行记录在硬盘上都有物理存储编号
------------------------------------------------------------------------
100                     zhangsan                0x1111
120                     lisi                    0x2222
99                      wangwu                  0x8888
88                      zhaoliu                 0x9999
101                     jack                    0x6666
55                      lucy                    0x5555
130                     tom                     0x7777

【提醒1】:在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引,因为id是PK。另外在mysql中,一个字段上如果有unique约束的话,也会自动创建索引对象。

【提醒2】:在任何数据库中,任何一张表的任何一条记录在硬盘存储上都有一个物理地址

【提醒3】:在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在myisam存储引擎中,索引存储在.myi文件中。在innodb中,存储在一个逻辑名称为tablespace中。在memory中,存储在内存中。

1.3、mysql自动添加索引

在mysql当中,主键上,以及unique字段上都会自动添加索引的!!!!

1.4 索引的优化

什么条件下,我们会考虑给字段添加索引呢?
条件1:数据量庞大(到底有多么庞大算庞大,这个需要测试,因为每一个硬件环境不同)
条件2:该字段经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描。
条件3:该字段很少的DML(insert delete update)操作。(因为DML之后,索引需要重新排序!!!时间倍增!!!

建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。
建议通过主键查询,建议通过unique约束的字段进行查询(因为这里有索引),效率是比较高的。

1.5 索引的创建、删除
  1. 创建索引

    #给emp表的ename字段添加索引,起名:emp_ename_index
    create index emp_ename_index on emp(ename);
    
  2. 删除索引

    #将emp表上的emp_ename_index索引对象删除
    drop index emp_ename_index on emp;
    
1.6 查看SQL语句是否使用了索引进行检索

使用explain关键字

#未添加索引,直接查询非主键
explain select * from emp where ename = 'KING';
#直接查询主键(自动添加索引)
explain select * from emp where empno = 7566;
#给非主键添加索引后查询
create index emp_ename_index on emp(ename);
explain select * from emp where ename = 'KING';
1.7 索引失效(优化策略)
  1. 对含索引字段进行模糊查询时,如果以%开头,那么不会使用索引

    explain select * from emp where ename like '%T';
    

    优化策略:模糊查询是不使用%开头

  2. 如果使用or,则两边字段都要有索引,否则索引失效

    explain select * from emp where ename = 'KING' or job = 'MANAGER';
    
  3. 使用复合索引,需要使用左侧的列查找,否则索引失效

    • 复合索引:两个及两个以上字段,联合起来添加一个索引

      create index emp_job_sal_index on emp(job,sal);
      
      explain select * from emp where job = 'MANAGER';
      explain select * from emp where sal = 5000;
      
  4. where中索引列不能参与运算,否则索引失效

    create index emp_sal_index on emp(sal);
    explain select * from emp where sal*2 = 1600;
    
  5. where中索引列不能使用函数

    explain select * from emp where lower(ename) = 'smith';
    
1.8 数据库优化重要手段:索引

数据库优化时,首先考虑的就是索引。

  1. 单一索引:一个字段上添加索引

  2. 复合索引:两个及两个以上字段上添加索引

  3. 主键索引:主键上添加索引(主键和unique键自动添加索引)

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

【注意】:唯一性比较弱的字段上,添加索引用处不大

2、视图(View)

2.1 什么是视图

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

2.2 创建/删除视图对象
  1. 只有DQL语句才能以view的形式创建,相当于地址

    • create view dept2_view as(DQL语句);
      
#先建一个表用于演示视图
create table dept as (select * from dept);
#创建视图对象
create view dept2_view as select * from dept2;
#删除视图
drop view dept2_view;
2.3 视图的作用:类似JAVA引用
  1. 我们可以面向视图对象进行增删改查,对视图对象的增删改,会导致原表被操作!
  2. 特点:对视图的操作,会影响到原表数据。
#面向视图查询
select * from dept2_view; #面向视图插入
insert into dept2_view(deptno,dname,loc) values(60,'SALES', 'BEIJING');#查询原表数据
select * from dept2;
#创建两个表连接的视图
create view emp_dept_view
as(select e.ename, e.sal, d.dnamefrom emp ejoindept done.deptno = d.deptno
);
#查询视图对象
select * from emp_dept_view;
+--------+---------+------------+
| ename  | sal     | dname      |
+--------+---------+------------+
| SMITH  |  800.00 | RESEARCH   |
| ALLEN  | 1600.00 | SALES      |
| WARD   | 1250.00 | SALES      |
| JONES  | 2975.00 | RESEARCH   |
| MARTIN | 1250.00 | SALES      |
| BLAKE  | 2850.00 | SALES      |
| CLARK  | 2450.00 | ACCOUNTING |
| SCOTT  | 3000.00 | RESEARCH   |
| KING   | 5000.00 | ACCOUNTING |
| TURNER | 1500.00 | SALES      |
| ADAMS  | 1100.00 | RESEARCH   |
| JAMES  |  950.00 | SALES      |
| FORD   | 3000.00 | RESEARCH   |
| MILLER | 1300.00 | ACCOUNTING |
+--------+---------+------------+
#面向视图更新【谨慎修改,原表数据也变了】
update emp_dept_view set sal = 1000 where dname = 'ACCOUNTING';
#查询原表
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 | 1000.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 1000.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 | 1000.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
2.4 视图对象在实际开发中的作用
  1. 提高代码复用、简化开发、利于维护
  2. 比如视图emp_dept_view就代表了下面的两表连接查询语句,该视图对象即代表了复杂的查询语句。
  3. 存储在硬盘内。如果将查询结果直接新建表,并不能修改原表
#创建两个表连接的视图
create view emp_dept_view
as(select e.ename, e.sal, d.dnamefrom emp ejoindept done.deptno = d.deptno
);

【注意】:
1. 视图对应的语句只能是DQL语句。
2. 但是视图对象创建完成之后,可以对视图进行增删改查等操作。

【CRUD】:
增删改查,又叫做:CRUD。
CRUD是在公司中程序员之间沟通的术语。一般我们很少说增删改查。
一般都说CRUD。

C: Create (增)
R: Retrieve(查:检索)
U: Update (改)
D: Delete (删)

3、DBA常用命令

database administrator,数据库管理员

3.1 重点掌握
  • 数据的导入和导出(数据备份)

    • 导入
    • 导出
  • 其他命令了解即可
    • 新建用户
    • 授权
    • 回收权限
3.2 数据导出

​ 在windows的dos命令窗口:

  • mysqldump 数据库名>文件路径存放文件名.sql -uroot -p123456
    
    #删除库
    drop database bjpowernode;
    
  • 导出指定表

    mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot -p123456
    
3.3 数据导入

【source】

​ step 1. 先登录到mysql数据库服务器上

​ step 2. 创建数据库:create database bjpowernode;

​ step 3. 使用数据库:use bjpowernode

​ step 4. 初始化数据库:source D:\bjpowernode.sql

4、数据库设计的三范式(重要)

4.1 什么是数据库设计范式

数据库表的设计规则

4.2 数据库设计三大范式
  • 第一范式:要求任何一张表都必须要有主键,每一个字段原子性不可再分
  • 第二范式:建立在的第一范式基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖
  • 第三范式:建立在第二范式基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖

【注意】:面试官经常问三范式,要熟记于心

按照三大范式进行数据库表设计,可以避免表中数据的冗余,空间的浪费

单一主键满足第二范式,但是复合主键可能产生部份依赖,不满足第二范式

4.3 第一范式
  1. 最核心,最重要的范式,所有表的设计都需要满足

  2. 必须要有主键,并且每一个字段都是原子不可再分

学生编号   学生姓名     联系方式
------------------------------------------
1001        张三      zs@gmail.com,1359999999
1002        李四      ls@gmail.com,13699999999
1001        王五      ww@163.net,13488888888

上表不满足第一范式:没有主键;联系方式可以分为邮箱地址和电话

学生编号(pk) 学生姓名    邮箱地址         联系电话
----------------------------------------------------
1001        张三      zs@gmail.com   1359999999
1002        李四      ls@gmail.com   13699999999
1003        王五      ww@163.net     13488888888
4.4 第二范式
  1. 建立在第一范式的基础之上
  2. 要求所有的非主键字段必须【完全依赖】主键字段,不要产生【部分依赖】
学生编号 学生姓名 教师编号 教师姓名
----------------------------------------------------
1001    张三    001     王老师
1002    李四    002     赵老师
1003    王五    001     王老师
1001    张三    002     赵老师
  1. 没有主键,不满足第一范式
  2. 不满足第二范式:
    1. 这张表满足了学生和老师的关系:(1个学生可能对应多个老师,1个老师有多个学生)
    2. 这是非常典型的【多对多关系】!!!:3表2外键

【修改1】满足第一范式:复合主键(PK: 学生编号+教师编号)

单一主键满足第二范式,但是复合主键可能产生部份依赖,不满足第二范式

学生编号+教师编号(pk) 学生姓名 教师姓名


​ 1001 001 张三 王老师
​ 1002 002 李四 赵老师
​ 1003 001 王五 王老师
​ 1001 002 张三 赵老师

经过修改之后,上表仍然 不满足第二范式:

  1. “张三”依赖1001,“王老师”不依赖1001,而依赖001,显然产生了部分依赖。
  2. 产生部分依赖造成:数据冗余了。空间浪费了。“张三”重复了,“王老师”重复了。

【修改2】:创建三张表:学生表、教师表、学生教师关系表

【多对多设计原则】:多对多->三张表->关系表有两个外键

学生表
学生编号(pk)    学生名字
------------------------------------
1001            张三
1002            李四
1003            王五
教师表
教师编号(pk)    教师姓名
--------------------------------------
001             王老师
002             赵老师
学生教师关系表
id(pk)      学生编号(fk)    教师编号(fk)------------------------------------------------------
1             1001          001
2             1002          002
3             1003          001
4             1001          002
4.5 第三范式
  1. 第三范式建立在第二范式的基础之上
  2. 要求所有非主键字段必须【直接依赖】主键,不产生【传递依赖】
学生编号(PK) 学生姓名 班级编号  班级名称
-------------------------------------1001    张三     01      一年一班1002     李四     02      一年二班1003     王五     03      一年三班1004     赵六     03      一年三班

以上表的设计是描述:班级和学生的关系。很显然是1对多关系!

  1. 满足第一范式:有主键

  2. 满足第二范式:不是复合主键,没有产生部份依赖。主键是单一主键

  3. 不满足第三范式:产生了传递依赖(班级名称->班级编号->学生编号),不符合第三范式的要求,产生了数据冗余

【修改】:一对多,两张表,多的表加外键!!!

班级表:一
班级编号(pk)     班级名称
01              一年一班
02              一年二班
03              一年三班
学生表:多
学生编号(PK)学生姓名   班级编号(fk)
--------------------------------
1001        张三      01
1002        李四      02
1003        王五      03
1004        赵六      03
4.6 总结表的设计(牢记)

【一对多】:

一对多,两张表,多的表加外键fk!!!!!!!!!!!!

【多对多】

多对多,三张表,关系表两个外键fk!!!!!!!!!!!!!!!

【一对一】

口诀:一对一,外键fk且唯一unique!!!!!!!!!!

在实际的开发中,可能存在一张表字段太多,太庞大。这个时候要拆分表。
一对一怎么设计?

没有拆分表之前:一张表
t_user
id  login_name  login_pwd   real_name email         address........
-------------------------------------------------------------------------
1   zhangsan    123         张三       zhangsan@xxx
2   lisi        123         李四       lisi@xxx
...

这种庞大的表建议拆分为两张

t_login 登录信息表
id(pk)      login_name      login_pwd
---------------------------------
1           zhangsan        123
2           lisi            123         t_user 用户详细信息表
id(pk)      real_name       email           login_id(fk+unique)
-------------------------------------------------------------------------
100         张三              zhangsan@xxx   1
200         李四              lisi@xxx      2
4.7 总结

数据库设计指导:

数据库设计三范式是理论上的,但是理论和实践具有偏差,最终的目的都是为了满足客户的需求,有的时候就要拿冗余换执行速度。

因为在SQL中,表和表之间连接次数越多,效率越低(笛卡尔积)。

有时存在冗余,却会减少表的连接次数,这样也是合理的,同时数据库表的SQL开发和维护难度也会降低。

【内容详细、源码详尽】MySQL极简学习笔记相关推荐

  1. 微信棋牌游戏源码搭建HTML5极简的JS函数

    页面初始化 mui框架将很多功能配置都集中在mui.init方法中,要使用某项功能,只需要在mui.init方法中完成对应参数配置即可,目前支持在mui.init方法中配置的功能包括:创建子页面.关闭 ...

  2. 基于python3写的源码剖析_Python 极简插件系统 pluggy 源码剖析

    前言 本长文不适合手机端阅读,请酌情退出 公司架构组基于 pytest 自研了一套测试框架 sstest,目的是为了让业务组(也就是我在的组)更好的写单元测试,从而提高代码质量,单元测试的目的是为了回 ...

  3. 嵌入式之uboot源码分析-启动第一阶段学习笔记

    注: 以下的内容来自朱老师物联网大讲堂uboot部分课件 Uboot启动第一阶段start.S执行步骤 1.头文件包含 <config.h>(x210的各种宏定义) <version ...

  4. AFL源码分析之afl-fuzz(学习笔记)(一)

    文章目录 一.源码 1.信号处理函数 2.check_asan_opts(检查内存错误) 3.fix_up_sync(检查ID.sync_id是否过长,检查互斥) 4.save_cmdline(将当前 ...

  5. AFL源码分析之afl-fuzz(学习笔记)(二)

    文章目录 前言 1.shmget(key_t key, size_t size, int shmflg)函数 2.shmat(int shm_id, const void *shm_addr, int ...

  6. as工程放到源码编译_方舟编译器学习笔记2 源码编译

    根据方舟官方文档编译了方舟编译器的源码,在这里简单谈谈其源码的编译过程: 1.操作系统环境: 64位版本的Ubuntu(官方推荐Ubuntu 16.04).我自己本身就有Ubuntu 16.04的虚拟 ...

  7. AFL源码分析之afl-clang-fast(学习笔记)

    前言 通过afl-gcc来插桩这种做法已经属于不建议,更好的就是afl-clang-fast工具是通过llvm pass来插桩. #ifdef 是判断某个宏是否被定义,若已定义,执行随后的语句 #en ...

  8. Lerx开源网站内容管理系统(CMS) v6.5 以Java+MySQL进行开发的内容管理系统源码

    介绍 Lerx 开源网站内容管理系统(CMS)是一个以Java+MySQL进行开发的内容管理系统源码. Lerx 开源网站内容管理系统(CMS)特点: 1.跨平台设计,能无差别运行于Windows.L ...

  9. 自动化测试如何保持登录状态_自动化测试po模式是什么?自动化测试po分层如何实现?-附详细源码...

    一.什么是PO模式 全称:page object model 简称:POM/PO PO模式最核心的思想是分层,实现松耦合!实现脚本重复使用,实现脚本易维护性! 主要分三层: 1.基础层BasePage ...

最新文章

  1. ValueError: need at most 63 handles, got a sequence of length 65
  2. 罗马数字转阿拉伯数字
  3. 构建之法 第三次心得
  4. linux内存管理简介,Linux操作系统的内存管理特性简介 (3)
  5. 第四部分 Calendar使用示例
  6. python反距离权重法_反距离权重法 (Spatial Analyst)—ArcMap | 文档
  7. 如何取消IntelliJ IDEA打开默认项目配置
  8. 复习各种符号 字符 巩固基础2
  9. 淘晶驰串口屏常见问题及解决方法
  10. 软考高项——计算专题
  11. Filezilla server 使用教程
  12. cocos2d-x游戏开发 《坠入蔚蓝》
  13. Linux unison 效率,Linux下inotify+unison双向同步环境部署
  14. 2020最后一天,一起回顾这不平凡的一年...
  15. 美国计算机硕士要读多久,去美国读研究生需要多久 各专业时长一览
  16. 短途游成了携程、美团、抖音眼中的“香饽饽”?
  17. 在3小时内学习Kubernetes:编排容器的详细指南
  18. js增加透明css样式,如何配置透明发光的骚气 vscode
  19. 基于单片机的篮球计数器设计
  20. Java如何创建支付接口

热门文章

  1. 知乎:有哪些让你相见恨晚的 PPT 制作技术或知识?
  2. vertica资源管理
  3. 京东暑期实习面经(已OC)
  4. win10 ie浏览器卸载后无法重启,试了网上各种方法都无法重启
  5. 微信公众平台的STRUTS
  6. 全球屏占比最高!华为MatePad Pro震撼发布
  7. Github上8个很棒的Vue项目
  8. ELementUI select多选下拉框获取选中项的全部属性
  9. 大数据、互联网、机器人成大热门
  10. unity复现中的错误