栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

MySQL学习笔记

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MySQL学习笔记

文章目录
        • 一、数据库概述及数据准备:
          • ①SQL、DB、DBMS:
          • ②表_table:
          • ③SQL语句分类:
          • ④导入数据:
          • ⑤查看表结构:
          • ⑥查看表中的数据:
        • 二、常用命令:
          • ①查看MySQL版本:
          • ②创建数据库:
          • ③查询当前使用的数据库:
          • ④终止语句:
          • ⑤退出MySQL:
          • ⑥查看创建表的语句:
        • 三、简单的查询
        • 四、条件查询:
        • 五、数据排序
        • 六、分组函数和分组查询
          • ①分组函数:
          • ②分组查询:
          • ③小结:
        • 七、连接查询
          • ①什么是连接查询?
          • ②连接查询的分类:
          • ③笛卡尔积现象:
          • ④内连接之等值连接:
          • ⑤内连接之非等值连接:
          • ⑥自连接:
          • ⑦外连接:
          • ⑧多张表进行操作:
        • 八、子查询:
        • 九、`union`
        • 十、`limit`
        • 十一、表及数据的增删查改
          • ①表的创建_`create`:
          • ②数据的插入_`insert`:
          • ③修改数据_`update`:
          • ④表及数据的删除:
        • 十二、表结构的增删改
          • ①添加字段:
          • ②修改字段:
          • ③删除字段:
        • 十三、创建表加上约束
          • ①非空约束_`not null`:
          • ②唯一性约束_`unique`:
          • ③主键约束:
          • ④外键约束:
          • ⑤级联更新与级联删除:
        • 十四、存储引擎
          • ①什么是存储引擎?
          • ②存储引擎的使用:
          • ③常用的存储引擎:
          • ④存储引擎的选择:
        • 十五、事务
          • ①基本介绍:
          • ②自动提交模式:
          • ③事务的隔离级别:
          • ④演示事务:
          • ⑤设置服务器缺省隔离级别:
        • 十六、索引
          • ①索引原理:
          • ②索引的相关使用:
          • ③索引的分类:
          • ④索引什么时候失效?
        • 十七、视图
          • ①视图的基本介绍:
          • ②视图的使用:
        • 十八、DBA命令
          • ①将数据库中的数据导出:
          • ②导入数据:
        • 十九、数据库设计三范式
          • ①什么是设计范式?
          • ②三范式的基本介绍:
          • ③三范式小结:
        • END

一、数据库概述及数据准备: ①SQL、DB、DBMS:
  • DB:

    • Database——数据库,数据库实际上在硬盘上以文件的形式存在。
  • DBMS:

    • D a t a base M a n a g e m e n t S y s t e m Database Management System DataBaseManagementSystem——数据库管理系统,常见的有:MySQL、Oracle、SQLServer……
  • SQL:

    • 结构化查询语言,是一门标准通用的语言,标准的 SQL 语句适合于所有的数据库产品;SQL 属于高级语言;SQL 语句在执行的时候,实际上内部也会先进行编译,然后再执行 SQL,SQL 语句的编译由 DBMS 完成。
  • 彼此之间的关系:

    • DBMS负责执行 SQL 语句,通过执行 SQL语句来操作 DB中的数据。
    • DBMS—(执行)—>SQL—(操作)—>DB。
②表_table:
  • 什么是表?

    • table 是数据库的基本组成单位,所有的数据都以表格的形式组织,目的是可读性强。
  • 一个表包含行和列:

    • 行——被称为数据/记录(data)。

    • 列——被称为字段(column)

      学号(int)姓名(varchar)年龄(int)
      20181101张三21
      20181103李四22
    • 每一个字段应该包含哪些属性?

      • 字段名、数据类型、相关的约束。
③SQL语句分类:
分类介绍
DQL(数据查询语言)查询语句,凡是select语句都是DQL。
DML(数据操作语言)insert delete update,对表当中的数据进行增删改。
DDL(数据定义语言)create drop alter,对表结构的增删改。
TCL(事务控制语言)commit提交事务,rollback回滚事务。(TCL中的T是Transaction)
DCL(数据控制语言)grant授权、revoke撤销权限等。
④导入数据:
  • 登录 MySQL 数据库管理系统:

    mysql -uroot -p密码
    

  • 查看有哪些数据库:

    show databases;
    

  • 创建自己的数据库:

    create database 数据库名;
    

  • 使用数据库的数据:

    use 数据库名;
    

  • 查看当前使用的数据库中有哪些表:

    show tables;
    

    • 因为是新建的数据库,所以内部暂时还空空如也。
  • 初始化数据:

    source sql文件路径;
    

    • test.sql,这个文件以 sql 结尾,这样的文件被称为“sql脚本”。什么是 sql 脚本呢?

    • 当一个文件的扩展名是.sql,并且该文件中编写了大量的sql语句,我们称这样的文件为sql脚本。

      • 注意:直接使用source命令可以执行sql脚本
      • sql脚本中的数据量太大的时候,无法打开,请使用source命令完成初始化。
    • test.sql 文件中的代码:

    DROP TABLE IF EXISTS EMP;
    DROP TABLE IF EXISTS DEPT;
    DROP TABLE IF EXISTS SALGRADE;
    
    CREATE TABLE DEPT
           (DEPTNO int(2) not null ,
    	DNAME VARCHAR(14) ,
    	LOC VARCHAR(13),
    	primary key (DEPTNO)
    	);
    CREATE TABLE EMP
           (EMPNO int(4)  not null ,
    	ENAME VARCHAR(10),
    	JOB VARCHAR(9),
    	MGR INT(4),
    	HIREDATE DATE  DEFAULT NULL,
    	SAL DOUBLE(7,2),
    	COMM DOUBLE(7,2),
    	primary key (EMPNO),
    	DEPTNO INT(2) 
    	)
    	;
    
    CREATE TABLE SALGRADE
          ( GRADE INT,
    	LOSAL INT,
    	HISAL INT );
    
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
    10, 'ACCOUNTING', 'NEW YORK'); 
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
    20, 'RESEARCH', 'DALLAS'); 
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
    30, 'SALES', 'CHICAGO'); 
    INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES ( 
    40, 'OPERATIONS', 'BOSTON'); 
    commit;
     
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7369, 'SMITH', 'CLERK', 7902,  '1980-12-17'
    , 800, NULL, 20); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7499, 'ALLEN', 'SALESMAN', 7698,  '1981-02-20'
    , 1600, 300, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7521, 'WARD', 'SALESMAN', 7698,  '1981-02-22'
    , 1250, 500, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7566, 'JONES', 'MANAGER', 7839,  '1981-04-02'
    , 2975, NULL, 20); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7654, 'MARTIN', 'SALESMAN', 7698,  '1981-09-28'
    , 1250, 1400, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7698, 'BLAKE', 'MANAGER', 7839,  '1981-05-01'
    , 2850, NULL, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7782, 'CLARK', 'MANAGER', 7839,  '1981-06-09'
    , 2450, NULL, 10); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7788, 'SCOTT', 'ANALYST', 7566,  '1987-04-19'
    , 3000, NULL, 20); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7839, 'KING', 'PRESIDENT', NULL,  '1981-11-17'
    , 5000, NULL, 10); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7844, 'TURNER', 'SALESMAN', 7698,  '1981-09-08'
    , 1500, 0, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7876, 'ADAMS', 'CLERK', 7788,  '1987-05-23'
    , 1100, NULL, 20); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7900, 'JAMES', 'CLERK', 7698,  '1981-12-03'
    , 950, NULL, 30); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7902, 'FORD', 'ANALYST', 7566,  '1981-12-03'
    , 3000, NULL, 20); 
    INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
    DEPTNO ) VALUES ( 
    7934, 'MILLER', 'CLERK', 7782,  '1982-01-23'
    , 1300, NULL, 10); 
    commit;
     
    INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
    1, 700, 1200); 
    INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 
    2, 1201, 1400); 
    INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 3, 1401, 2000); 
    INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 4, 2001, 3000); 
    INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES ( 5, 3001, 9999); 
    commit;
    
    • 执行完命令之后,我们再次查看数据库中的表:

  • 删除数据库:

    drop database 数据库名字;
    
    • 这个就不演示了,整完还得我重建!/(ㄒoㄒ)/~~
⑤查看表结构:
+----------------+
| Tables_in_test |
+----------------+
| 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    |       |部门地址
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
  • 员工表:
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    |       |部门编号
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.01 sec)
  • 工资等级表:
mysql> desc salgrade;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| GRADE | int(11) | YES  |     | NULL    |       |等级
| LOSAL | int(11) | YES  |     | NULL    |       |最低薪资
| HISAL | int(11) | YES  |     | NULL    |       |最高薪资
+-------+---------+------+-----+---------+-------+
3 rows in set (0.01 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)
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 salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+
5 rows in set (0.00 sec)

二、常用命令: ①查看MySQL版本:
  • 未登录MySQL之前:

    mysql -V
    
    mysql --version
    

    • MySQL程序选项具有如下两种通用形式:
      • 长选项——由单词之前加两个减号组成。
      • 短选项——由单个字母之前加一个减号组成。
  • 登录MySQL之后:

    select version();
    

②创建数据库:
create database 数据库名;

  • 在创建完数据库,建立表之前必须要先选择数据库:

    use 数据库名称;
    

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

④终止语句:
c

⑤退出MySQL:
q
quit
exit

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


三、简单的查询
  • 语法格式:

    select 字段名1,字段名2,字段名3,.... from 表名;
    
  • 注意:

    • 任何一条sql语句以;结尾。
    • sql语句不区分大小写。
  • 使用举例:

    • 查询员工的年薪(字段可以参与数学运算)

    • 给查询结果的列重命名(as可以省略)

    • 别名中含有中文(中文一定要使用''括起来,MySQL也支持"",但尽量别用)

    • 查询所有字段(实际开发中不建议使用*,效率较低)


四、条件查询:
  • 语法格式:

    select 
    	字段,字段...
    from
    	表名
    where
    	条件;
    
  • 执行顺序:先from,然后where,最后select。

  • 支持的运算符:

    运算符说明
    =等于
    <>或!=不等于
    <小于
    <=大于等于
    >大于
    >=大于等于
    between...and...两个值之间,等同于>= and <=
    is null为null(is not null不为空)
    and并且
    or或者
    in包含,相当于多个or(not in不在这个范围中)
    notnot可以取非,主要用在is或in中
    likelike称为模糊查询,支持%或下划线_匹配
  • 使用举例:

    • 查询工资等于5000的员工姓名

    • 查询SMITH的工资

    • 找出工资高于3000的员工(大于等于、小于、小于等于都一样的书写格式)

    • 找出工资不等于3000的

    • 找出工资在1100和3000之间的员工,包括1100和3000

      • between...and...是闭区间,在使用的时候必须左小右大。

    • between...and...除了可以使用在数字方面之外,还可以使用在字符串方面,此时为左闭右开。

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

    • 找出工作岗位是MANAGER或SALESMAN的员工

    • and 和 or 联合起来使用:找出薪资大于1000的并且部门编号是20或30部门的员工。(当运算符的优先级不确定的时候加小括号。)

    • in 等同于or:找出工作岗位是MANAGER和SALESMAN的员工

    • 模糊查询like:

      • 在模糊查询当中,必须掌握两个特殊的符号,一个是%,一个是_,%代表任意多个字符,_代表任意1个字符。
      • 找出名字中含有O的

      • 找出名字中第二个字母是A的

      • 找出名字中有下划线_的
        • 因为下划线_表示任意的一个字符,所以加上来表示_本身来使用,%也是类似的。

      • 找出名字最后的一个字符是T的


五、数据排序

排序采用 order by 子句,order by 后面跟上排序字段,排序字段可以放多个,多个采用逗号间隔,order by 默认采用升序,如果存在 where 子句那么 order by 必须放到 where 语句的后面。

  • 按照工资升序,找出员工名字和薪资:
select 
	ename,sal 
from 
	emp 
order by
	sal;

  • 注意:默认是升序。但是我们可以指定升序或者降序——asc表示升序,desc表示降序。

  • 使用多个排序条件:按照工资的降序排列,当工资相同的时候再按照名字的升序排列。

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

  • 和where联合起来使用:存在 where 子句那么 order by 必须放到 where 语句的后面。

    select                    执行顺序
    	字段						3
    from
    	表名						1
    where
    	条件						2
    order by
    	....					 4
    	
    order by是最后执行的。
    
    • 找出工作岗位是SALESMAN的员工,并且要求按照薪资的降序排列。

  • 使用字段的位置进行排序:不建议使用此种方式,采用数字含义不明确,程序健壮性不好。


六、分组函数和分组查询 ①分组函数:
  • 所有的分组函数都是对“某一组”数据进行操作的。分组函数还有另一个名字:多行处理函数。多行处理函数的特点:输入多行,最终输出的结果是1行
字段名意义
count取得记录条数
sum求和
avg取得平均数
max取得最大的数
min取得最小的数
  • 注意:

    • ①分组函数自动忽略空值,不需要手动加where条件来排除空值。

    • ②分组函数不能直接使用在where关键字后面

  • count:取得记录条数。

    • 取得所有的员工数:

    • Count(*)表示取得所有记录,不是统计某个字段中数据的个数,而是统计总记录条数(和某个字段无关),忽略 null,为 null 的值也会取得。
    • 取得津贴不为null员工数:

    • 采用 count(字段名称),表示统计字段中不为null的数据总数量,不会取得为 null 的记录。
    • 取得工作岗位的个数:

    • 使用distinct目的是为了去重,后面小结板块会详细讲讲。

  • sum:sum会取得某一列的和,null会自动忽略。

    • 取得薪水的和:

    • 取得津贴的和:null会被自动忽略。

    • 取得薪水的合计:

    • 从以上结果来看,不正确,原因在于 comm 字段有 null 值,所以无法计算,sum 会忽略掉,正确的做法是将 comm 字段转换成 0;为此我们要借助ifnull()空处理函数——可能为NULL的数据,被当做什么处理。

  • avg:取得某一列的平均值

    • 取得平均薪水:

  • max:取得某一列的最大值。

    • 取得最高薪水:

    • 取得最晚入职得员工:

  • min:取得某个一列的最小值。

    • 取得最低薪水:

    • 取得最早入职得员工(可以不使用 str_to_date 转换)

  • 分组函数也可以组合起来用:

    • 但是切记:分组函数不能直接使用在where关键字后面。

    • 可以分布执行来解决上面提出的不能在where关键字后面使用分组函数的问题(语句嵌套),例如:找出工资高于平均工资的员工。

      • 算出平均工资:

      • 找出高于平均工资的员工:

      • 最终整合:

②分组查询:
  • group by : 按照某个字段或者某些字段进行分组。

    • 实际举例:找出每个工作岗位的最高薪资:

    • 注意:分组函数一般都会和group by联合使用,这也是为什么它被称为分组函数的原因。 并且任何一个分组函数count、sum、avg、max、min都是在group by语句执行结束之后才会执行的。当一条sql语句没有group by的话,整张表的数据会自成一组。

    • 书写注意:

      select ename,max(sal),job from emp group by job;
      
    • 以上在mysql当中,查询结果是有的,但是结果没有意义,在Oracle数据库当中会报错。语法错误。Oracle的语法规则比MySQL语法规则严谨。

    • 记住一个规则:当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段

  • having : 对分组之后的数据进行再次过滤。

    • 实际举例:取得每个岗位的平均工资大于 2000

    • 特殊情况:但是有一些情况下的查询可以不必使用having就能实现,并且效率更快。

      • 找出每个部门的最高薪资,要求显示薪资大于2900的数据。

        • 找到每个部门的最高薪资

        • 找到薪资大于2900的

        • 可以不借助having在where中就可以实现上述功能

      • 这样的效率较高,建议能够使用where过滤的尽量使用where,因为where的执行顺序在having前面,早一步过滤的话可以减少处理的数据量,提高效率(但是谨记一点:where后面不能使用分组函数,这个使用就只能使用having了)。

③小结:
  • 一个完整的DQL语句:

                 执行顺序
    select		    5
    	...
    from			1	
    	...
    where			2
    	...
    group by		3
    	...
    having		    4
    	...
    order by		6
    	...
    
    • 个人理解:先知道要处理什么表(from),再通过条件(where)选中原表中的一些行,对于这些行进行分组(group up),分完组之后再度过滤(having),然后通过(select)构建新表的列;最终排序(order by)呈现新表。
  • 对于查询结果集的去重_distinct:

    • 查看所有的工作种类:

    • 错误举例:

      select ename,distinct job from emp;
      
      • 以上的sql语句是错误的,distinct只能出现在所有字段的最前面。

    • 其他正确使用举例:

      select distinct deptno,job from emp;
      

      select count(distinct job) from emp;
      


七、连接查询 ①什么是连接查询?
  • 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
  • 连接查询:也可以叫跨表查询,需要关联多个表进行查询。
②连接查询的分类:
  • 根据语法出现的年代来划分的话,包括:

    • SQL92(一些老的DBA可能还在使用这种语法。DBA:Database Administrator,数据库管理员)
    • SQL99(比较新的语法)
  • 根据表的连接方式来划分,包括:

③笛卡尔积现象:

在表的连接查询方面有一种现象被称为:笛卡尔积现象。(笛卡尔乘积现象)

  • 实际举例:找出每一个员工的部门名称,要求显示员工名和部门名。

  • 笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积

  • 书写小技巧:给表起别名(以上面的查询案例举例)

    select e.ename,d.dname from emp e,dept d;
    
    • 起别名的好处:执行效率高,可读性好。
  • 如何避免笛卡尔积现象——加条件进行过滤(还是以上面的查询案例举例:找出每一个员工的部门名称,要求显示员工名和部门名)。

    • 避免了笛卡尔积现象,并不会减少记录的匹配次数,次数还是56次。只不过显示的是有效记录

④内连接之等值连接:
  • 最大的特点——条件为等量关系

  • 实际举例:查询每个员工的部门名称,要求显示员工名和部门名。

    • SQL92:比较老旧的语法,不怎么使用了。

    • SQL99:现在比较常用的语法。

      • 或者,inner可以省略的,带着inner目的是可读性好一些。
      select 
      	e.ename,d.dname
      from
      	emp e
      inner join
      	dept d
      on
      	e.deptno = d.deptno;
      
      • 语法:SQL99语法结构更清晰一些,表的连接条件和后来的where条件分离了
      ...
      	A
      (inner) join
      	B
      on
      	连接条件
      where
      	...
      
⑤内连接之非等值连接:
  • 最大的特点——连接条件中的关系是非等量关系

  • 实际举例:找出每个员工的工资等级,要求显示员工名、工资、工资等级。

    • 辅助信息:

    • 查询结果:

⑥自连接:
  • 最大的特点——一张表看做两张表来用,自己连接自己。
  • 实际举例:找出每个员工的上级领导,要求显示员工名和对应的领导名。

⑦外连接:
  • 什么是外连接,和内连接有什么区别?

    • 内连接:假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。AB两张表没有主副之分,两张表是平等的
    • 外连接:假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
  • 外连接的分类?

    • 左外连接(左连接):表示左边的这张表是主表。

      表 1 left outer join 表 2 on 关联条件
      
    • 右外连接(右连接):表示右边的这张表是主表。

      表 1 right outer join 表 2 on 关联条件
      
    • 左连接有右连接的写法,右连接也会有对应的左连接的写法。

  • 实际举例:找出每个员工的上级领导?(所有员工必须全部查询出来。)

    • 内连接:

    • 外连接(左外连接/左连接)(outer可以省略)(a为主表):

    • 外连接(右外连接/右连接)(outer可以省略)(a为主表):

    • 外连接最重要的特点是:主表的数据无条件的全部查询出来
  • 联合使用:找出哪个部门没有员工?

    • 辅助信息:

    • 查询结果:

⑧多张表进行操作:
  • 以三张表为例:A表和B表先进行表连接,连接之后继续和C表进行连接。

    ....
    	A
    join
    	B
    join
    	C
    on
    ...
    
  • 实际举例:

    • 找出每一个员工的部门名称以及工资等级。

    • 找出每一个员工的部门名称、工资等级、以及上级领导。

    • 在书写上面的案例时,自己有一个小心得——左外和右外连接的使用时机要把握好,不然就起不到理想的效果(譬如下面就是用早了,导致不是每一个员工都显示出来了)。


八、子查询:
  • 什么是子查询?子查询都可以出现在哪里?

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

    select
    		..(select).
    from
    		..(select).
    where
    		..(select).
    
  • where子句中使用子查询:

    • 找出高于平均薪资的员工信息(where后面不能直接使用分组函数)。

      • 找出平均薪资:

      • 使用where对于原表进行过滤:

      • 合并上面两步:

  • from后面嵌套子查询:

    • 找出每个部门平均薪水的等级。

      • 找出每一个部门的平均薪水(按照部门编号进行分组,求sal的平均值)

      • 将以上的查询结果当做临时表t,让t表和salgrade表进行连接

  • 在select后面嵌套子查询:

    • 找出每个员工所在的部门名称,要求显示员工名和部门名。

      • 做法一:

      • 做法二:


九、union

union 可以合并集合,也就是可以将查询结果集相加。

  • 实际案例:找出工作岗位是SALESMAN和MANAGER的员工?

    • 方法一_or:

    • 方法二_in:

    • 方法三_union:

  • 注意:合并结果集的时候,需要查询字段个数相同,而且还要求类型对应相同。


十、limit
  • 特点介绍:

    • limit是MySQL特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)。

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

  • 语法机制:

    limit startIndex, length
    
    • startIndex表示起始位置,默认从0开始,0表示第一条数据,length表示取几个。
    • 实际举例:取出工资前5名的员工(降序取前5个)

  • limit是sql语句最后执行的一个环节:

                 执行顺序
    select			5
    		...
    from			1
    		...		
    where			2
    		...	
    group by		3
    		...
    having			4
    		...
    order by		6
    		...
    limit			7
    		...;
    

十一、表及数据的增删查改 ①表的创建_create:
  • 建表的语法格式:

    create table 表名(
    	字段名1 数据类型,
    	字段名2 数据类型,
    	字段名3 数据类型,
    	....
    );
    
  • sql中字段常见的数据类型:

    类型介绍
    int整数型(Java中的int)
    bigint长整型(Java中的long)
    float浮点型(Java中的float、double
    char定长字符串(String)
    varchar可变长字符串(StringBuffer、StringBuilder)
    date日期类型 (对应Java中的java.sql.Date类型)
    BLOB二进制大对象(存储图片、视频等流媒体信息)
    Binary Large Object(对应Java中的Object)
    CLOB字符大对象(存储较大文本,比如,可以存储4G的字符串。)
    Character Large OBject(对应Java中的Object)
    ......
  • char和varchar怎么选择?

    • 在实际的开发中,当某个字段中的数据长度不发生改变的时候,是定长的,例如:性别、生日等都是采用char。
    • 一个字段的数据长度不确定,例如:简介、姓名等都是采用varchar。
  • 表名在数据库当中一般建议以: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)
    	);
    
  • 表的复制:

    create table 表名 as select语句;
    //将查询结果当做表创建出来。
    

②数据的插入_insert:
  • 语法格式:

    insert into 表名(字段名1,字段名2,字段名3,....) values(值1,值2,值3,....)
    
    • 要求:字段的数量和值的数量相同,并且数据类型要对应相同
  • 实际举例:

    INSERT INTO t_student(NO,NAME,sex,classno,birth) VALUES(1,'zhangsan','1','gaosan1ban', '1950-10-12');
    

    insert into t_student(name) values('wangwu'); 
    //除name字段之外,剩下的所有字段自动插入NULL。
    

  • 注意事项:

    • 当一条insert语句执行成功之后,表格当中必然会多一行记录。即使多的这一行记录当中某些字段是NULL,后期也没有办法在执行insert语句插入数据了,只能使用update进行更新。

    • 字段可以省略不写,但是后面的value对数量和顺序都有要求。

      insert into t_student values(1,'jack','0','gaosan2ban','1986-10-23');
      

      insert into t_student values(1,'jack','0','gaosan2ban');
      

    • 一次插入多行数据:

      insert into t_student
      		(no,name,sex,classno,birth) 
      	values
      		(3,'rose','1','gaosi2ban','1952-12-14'),(4,'laotie','1','gaosi2ban','1955-12-14');
      

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

    • 当然插入表和查询结果形成的临时表的数据类型和字段要对应上。

③修改数据_update:
  • 语法格式:

    update 表名 set 字段名1=值1,字段名2=值2... where 条件;
    //没有设置条件则将整张表数据全部更新(where被省略)。
    
  • 实际案例:

    • 将部门10的LOC修改为SHANGHAI,将部门名称修改为RENSHIBU。

    • 更新所有的记录:

④表及数据的删除:
  • 数据的删除:

    • 语法格式:
    delete from 表名 where 条件;
    //没有设置条件则将表中数据全部删除(where被省略)。
    
    • 实际案例:

      • 删除10部门数据?

      • 删除所有的数据:

    • 大型表的删除:

    truncate table 表名; // 表被截断,不可回滚,永久丢失,效率比delete高。
    
  • 表的删除:

    drop table 表名; // 通用写法。
    drop table if exists 表名; // oracle不支持这种写法。
    


十二、表结构的增删改

采用 alter table 来增加/删除/修改表结构,不影响表中的数据。

①添加字段:
alter table 表名 add 字段名 数据类型;
  • 实际举例:给t_student表添加email字段,数据类型为varchar(30)。

②修改字段:
  • 修改字段的数据类型:

    alter table 表名 modify 字段名 数据类型;
    
    • 实际举例:将t_student表的name字段长度减少为100。

  • 修改字段的名称:

    alter table 表名 change 旧字段名 新字段名 数据类型;
    
    • 实际举例:将t_student表的sex字段名字改为gender。

③删除字段:
alter table 表名 drop 字段名;
  • 实际举例:删除t_student表的email字段。


十三、创建表加上约束

先介绍一个知识:可以使用**ConSTRAINT [约束名]**来命名一个约束的,后面会用到。

①非空约束_not null:
  • 非空约束,针对某个字段设置其值不为空,如:用户的姓名不能为空

②唯一性约束_unique:
  • 唯一约束修饰的字段具有唯一性,不能重复。但可以为NULL。

  • 实际举例:

    • 给某一列添加unique:
    drop table if exists t_user;
    create table t_user(
    	id int,
    	username varchar(255) unique  // 列级约束
    );
    insert into t_user values(1,'zhangsan');
    insert into t_user values(2,'zhangsan');
    ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'username'
    

    • 给两个列或者多个列添加unique:
    drop table if exists t_user;
    create table t_user(
    	id int, 
    	usercode varchar(255),
    	username varchar(255),
    	unique(usercode,username) 
        // 多个字段联合起来添加1个约束unique 【表级约束】
        //(usercode,username) 这一对的组合不能出现重复
    );
    
    insert into t_user values(1,'111','zs');
    insert into t_user values(2,'111','ls');
    insert into t_user values(3,'222','zs');
    select * from t_user;
    insert into t_user values(4,'111','zs');
    ERROR 1062 (23000): Duplicate entry '111-zs' 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 values(1,'111','zs');
    insert into t_user values(2,'111','ls');
    ERROR 1062 (23000): Duplicate entry '111' for key 'usercode'
    

  • 注意:not null约束只有列级约束,没有表级约束

  • 如何查看约束?

    use information_schema;
    select * from table_constraints where table_name = '表名'; //横着展示
    //或者
    select * from table_constraints where table_name = '表名'G //变成竖着展示
    

③主键约束:

每个表应该具有主键,主键可以标识记录的唯一性,主键分为单一主键和复合(联合)主键,单一主键是由一个字段构成的,复合(联合)主键是由多个字段构成的

  • 主键的相关介绍:

    • 主键相关的术语?
      • 主键约束 : primary key
      • 主键字段 : id字段添加primary key之后,id叫做主键字段。
      • 主键值 : id字段中的每一个值都是主键值。
    • 主键有什么作用?
      • 表的设计三范式中有要求,第一范式就要求任何一张表都应该有主键。
      • 主键的作用:主键值是这行记录在这张表当中的唯一标识。(就像一个人的身份证号码一样。)
    • 主键的分类?
      • 根据主键字段的字段数量来划分:
        • 单一主键(推荐的,常用的。)
        • 复合主键(多个字段联合起来添加一个主键约束)(复合主键不建议使用,因为复合主键违背三范式。)
      • 根据主键性质来划分:
        • 自然主键:主键值最好就是一个和业务没有任何关系的自然数。(这种方式是推荐的)
        • 业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键。(不推荐用)最好不要拿着和业务挂钩的字段作为主键。因为以后的业务一旦发生改变的时候,主键值可能也需要随着发生变化,但有的时候没有办法变化,因为变化可能会导致主键值重复。
    • 一张表的主键约束只能有一个
  • 实际举例:

    • 使用列级约束方式定义主键:
    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,'zs','zs@123.com');
    insert into t_user(id,username,email) values(2,'ls','ls@123.com');
    insert into t_user(id,username,email) values(3,'ww','ww@123.com');
    select * from t_user;
    
    insert into t_user(id,username,email) values(1,'jack','jack@123.com');
    //ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
    
    insert into t_user(username,email) values('jack','jack@123.com');
    //ERROR 1364 (HY000): Field 'id' doesn't have a default value
    

    • 根据以上的测试得出:id是主键,因为添加了主键约束,主键字段中的数据不能为NULL,也不能重复

    • 主键的特点:不能为NULL,也不能重复

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

    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,'zs');
    insert into t_user(id,username) values(2,'ls');
    insert into t_user(id,username) values(3,'ws');
    insert into t_user(id,username) values(4,'cs');
    select * from t_user;
    
    insert into t_user(id,username) values(4,'cx');
    //ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'
    

    • 复合主键(不推荐使用):
    drop table if exists t_user;
    create table t_user(
    	id int,
    	username varchar(255),
    	password varchar(255),
    	primary key(id,username)
    );
    insert .......
    
    • 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('b');
    insert into t_user(username) values('c');
    insert into t_user(username) values('d');
    insert into t_user(username) values('e');
    insert into t_user(username) values('f');
    select * from t_user;
    

    • 提示:Oracle当中也提供了一个自增机制——序列(sequence)对象。
④外键约束:

外键主要是维护表之间的关系的,主要是为了保证参照完整性,如果表中的某个字段为外键字段,那么该字段的值必须来源于参照的表的主键,如:emp 中的 deptno 值必须来源于 dept表中的 deptno 字段值。

  • 关于外键约束的相关术语:

    • 外键约束:foreign key。
    • 外键字段:添加有外键约束的字段。
  • 外键值:外键字段中的每一个值。

  • 实际案例:请设计数据库表,用来维护学生和班级的信息?

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

      no(主键)nameclassnoclassname
      1zs1101北京大兴区经济技术开发区亦庄二中高三1班
      2zs2101北京大兴区经济技术开发区亦庄二中高三1班
      3zs3102北京大兴区经济技术开发区亦庄二中高三2班
      4zs4102北京大兴区经济技术开发区亦庄二中高三2班
      5zs5102北京大兴区经济技术开发区亦庄二中高三2班
      • 缺点:过于冗余,不推荐使用。
    • 第二种方案:两张表(班级表和学生表)。

      • t_class班级表:
      cno(主键)cname
      101北京大兴区经济技术开发区亦庄二中高三1班
      102北京大兴区经济技术开发区亦庄二中高三2班
      • t_student学生表:
      sno(主键)snameclassno(应添加外键约束)
      1zs1101
      2zs2101
      3zs3102
      4zs4102
      5zs5102
    • 根据第二种方案书写建表语言:

      • 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),
      	constraint student_class foreign key(classno) references t_class(cno)//给约束起一个别名
      );
      
      insert into t_class values(101,'xxxxxxxxxx');
      insert into t_class values(102,'yyyyyyyyyy');
      //这里使用xxxx和yyyy取代班级的名字是因为编码的问题,cmd窗口是GBK,但是我的MySQL是UTF8,所以中文会出一点问题,我也懒得改了!
      insert into t_student values(1,'zs1',101);
      insert into t_student values(2,'zs2',101);
      insert into t_student values(3,'zs3',102);
      insert into t_student values(4,'zs4',102);
      insert into t_student values(5,'zs5',102);
      insert into t_student values(6,'zs6',102);
      select * from t_class;
      select * from t_student;
      

      • 此时插入一个学生数据,给sno赋予一个未在t_class进行说明的数据,因为外键约束的关系,会报错。
      insert into t_student values(7,'lisi',103);
      

  • 其他注意事项:

    • 外键值可以为NULL?

      • 外键可以为NULL,以上面的数据为例设计一个案例。

      • 这样会影响参照完整性,所以我们建议在表定义时将外键字段设置为非空。
    • 外键字段引用其他表的某个字段的时候,被引用的字段必须是主键吗?

      • 被引用的字段不一定是主键,但至少具有unique约束
⑤级联更新与级联删除:

mysql 对有些约束的修改比较麻烦,所以我们可以先删除,再添加(以上面的t_student和t_class表为例)。

  • 级联更新on update cascade:

    //先删除外键约束
    alter table t_student drop foreign key student_class;
    //再添加新的外键约束,加上级联更新
    alter table t_student add constraint student_class foreign key(classno) references t_class(cno) on update cascade;
    

    • 此时如果对父表t_class进行修改的话,t_student表中数据也会发生相应的修改。
    update t_class set cno=100 where cname='xxxxxxxxxx';
    

  • 级联删除on delete cascade:

    //先删除外键约束
    alter table t_student drop foreign key student_class;
    //再添加新的外键约束,加上级联删除
    alter table t_student add constraint student_class foreign key(classno) references t_class(cno) on delete cascade;
    

    • 此时如果对父表t_class进行删除的话,t_student表中数据也会发生相应的删除。


十四、存储引擎 ①什么是存储引擎?
  • 存储引擎这个名字只有在MySQL中存在。(Oracle中有对应的机制,但是不叫做存储引擎。Oracle中没有特殊的名字,就是“表的存储方式”)
  • MySQL支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。
②存储引擎的使用:
  • 数据库中的各表均被(在创建表时)指定的存储引擎来处理;在创建表时,可使用 ENGINE 选项为 CREATE TABLE语句显式指定存储引擎。

    CREATE TABLE `表名` (
    	  ......
    ) ENGINE=InnoDB(存储引擎) DEFAULT CHARSET=utf8(字符集);
    //建表的时候可以指定存储引擎,也可以指定字符集。
    
    • 如果在创建表时没有显式指定存储引擎,则该表使用当前默认的存储引擎;MySQL默认使用的存储引擎是InnoDB方式,默认采用的字符集是UTF8。
    • 默认的存储引擎可在 my.ini 配置文件中使用 default-storage-engine 选项指定。
    • 现有表的存储引擎可使用 ALTER TABLE 语句来改变:
    ALTER TABLE TABLENAME ENGINE = INNODB;
    
    • 为确定某表所使用的存储引擎,可以使用下面的语句:
    SHOW CREATE TABLE 表名G
    SHOW TABLE STATUS LIKE '表名'G
    

  • 服务器可用的引擎依赖于以下因素:MySQL 的版本、服务器在开发时如何被配置、启动选项。

  • 查看当前MySQL支持的存储引擎:

    show engines G
    

③常用的存储引擎:
  • MyISAM存储引擎:

          Engine: MyISAM
         Support: YES
         Comment: MyISAM storage engine
    Transactions: NO
              XA: NO
      Savepoints: NO
    
    • MyISAM这种存储引擎不支持事务。
    • MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。
    • MyISAM采用三个文件组织一张表:
      • xxx.frm(存储格式的文件)
      • xxx.MYD(存储表中数据的文件)
      • xxx.MYI(存储表中索引的文件)
    • 优缺点:
      • 优点:可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率
      • 缺点:不支持事务
  • InnoDB存储引擎:

          Engine: InnoDB
         Support: DEFAULT
         Comment: Supports transactions, row-level locking, and foreign keys
    Transactions: YES
              XA: YES
      Savepoints: YES
    
    • 优点:支持事务、行级锁、外键等。这种存储引擎数据的安全得到保障。
    • 表的结构存储在xxx.frm文件中。
    • 数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读
    • 这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制
    • InnoDB支持级联删除和级联更新
  • MEMORY存储引擎:

          Engine: MEMORY
         Support: YES
         Comment: Hash based, stored in memory, useful for temporary tables
    Transactions: NO
              XA: NO
      Savepoints: NO
    
    • 使用 MEMORY 存储引擎的表,其数据存储在内存中,且行的长度固定,这两个特点使得 MEMORY 存储引擎非常快
    • MEMORY 存储引擎管理的表具有下列特征:
      • 在数据库目录内,每个表均以.frm 格式的文件表示。
      • 表数据及索引被存储在内存中。
      • 表级锁机制。
      • 不能包含 TEXT 或 BLOB 字段。
    • 优缺点:
      • 缺点:不支持事务。数据容易丢失。因为所有数据和索引都是存储在内存当中的。
      • 优点:查询速度最快。
    • MEMORY 存储引擎以前被称为 HEAP 引擎。
④存储引擎的选择:
  • MyISAM 表最适合于大量的数据读而少量数据更新的混合操作。MyISAM 表的另一种
    适用情形是使用压缩的只读表。
  • 如果查询中包含较多的数据更新操作,应使用 InnoDB。其行级锁机制和多版本的支
    持为数据读取和更新的混合操作提供了良好的并发机制。
  • 可使用 MEMORY 存储引擎来存储非永久需要的数据,或者是能够从基于磁盘的表中
    重新生成的数据。

十五、事务 ①基本介绍:
  • 什么是事务?

    • 一个事务是一个完整的业务逻辑单元,不可再分
    • 事件举例:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:
    update t_act set balance = balance - 10000 where actno = 'act-001';
    update t_act set balance = balance + 10000 where actno = 'act-002';
    
    • 以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。
  • 事务相关的语句只有:DML语句(insert、delete、update)

    • 因为它们这三个语句都是和数据库表当中的“数据”相关的。事务的存在就是为了保证数据的完整性,安全性。
  • 事务的特性:

    • 原子性:事务是最小的工作单元,不可再分;整个事务中的所有操作,必须作为一个单元全部完成(或全部取消)。。
    • 一致性:事务必须保证多条DML语句同时成功或者同时失败,在事务开始之前与结束之后,数据库都保持一致状态。。
    • 隔离性:事务A与事务B之间具有隔离,一个事务不会影响其他事务的运行。。
    • 持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束;在事务完成以后,该事务对数据库所作的更改将持久地保存在数据库之中,并不会被回滚。
  • 事务中的一些概念:

    • 事务(Transaction):一批操作(一组 DML)
    • 开启事务(Start Transaction)
      • 执行DML 语句是其实就是开启一个事务
    • 回滚事务(rollback)
      • 关于事务的回滚需要注意:只能回滚 insert、delete 和 update 语句,不能回滚 select(回滚select 没有任何意义),对于 create、drop、alter 这些无法回滚。
    • 提交事务(commit)
      • rollback,或者 commit 后事务就结束了。
    • SET AUTOCOMMIT:禁用或启用事务的自动提交模式
②自动提交模式:
  • MySQL事务默认情况下是自动提交的;只要执行任意一条DML(insert、delete、update)语句则提交一次。可以使用start transaction;关闭自动提交

  • 启动自动提交模式下:

    • 如果自动提交模式被启用,则单条 DML 语句将缺省地开始一个新的事务。
    • 如果该语句执行成功,事务将自动提交,并永久地保存该语句的执行结果;如果语句执行失败,事务将自动回滚,并取消该语句的结果。
    • 在自动提交模式下,仍可使用 START TRANSACTION 语句来显式地启动事务;这时,一个事务仍可包含多条语句,直到这些语句被统一提交或回滚。
  • 禁用自动提交模式下:

  • 如果禁用自动提交,事务可以跨越多条语句;在这种情况下,事务可以用 COMMIT 和 ROLLBACK 语句来显式地提交或回滚。

  • 自动提交模式可以通过服务器变量 AUTOCOMMIT 来控制:

    SET AUTOCOMMIT = OFF;
    SET AUTOCOMMIT = ON;
    或
    SET SESSION AUTOCOMMIT = OFF;
    SET SESSION AUTOCOMMIT = ON;
    
    • 查看AUTOCOMMIT变量的状态:
    show variables like '%auto%';
    

③事务的隔离级别:
  • 事务的隔离级别决定了事务之间可见的级别。

  • 当多个客户端并发地访问同一个表时,可能出现下面的一致性问题:

    • 脏读取(Dirty Read):
      • 一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交,这就出现了脏读取。
    • 不可重复读(Non-repeatable Read):
      • 在同一个事务中,同一个读操作对同一个数据的前后两次读取产生了不同的结果,这就
        是不可重复读。
    • 幻像读(Phantom Read):
      • 幻像读是指在同一个事务中以前没有的行,由于其他事务的提交而出现的新行。
  • 四个隔离级别:

    • InnoDB 实现了四个隔离级别,用以控制事务所做的修改,并将修改通告至其它并发
      的事务:
    • 读未提交(READ UMCOMMITTED):
      • 允许一个事务可以看到其他事务未提交的数据
      • 存在脏读取(Dirty Read)现象。
    • 读已提交(READ COMMITTED):
      • 允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的
      • 解决了脏读取现象,但是存在不可重复读问题。
    • 可重复读(REPEATABLE READ):
      • 确保如果在一个事务中执行两次相同的 SELECT 语句,都能得到相同的结果,不管其他事务是否提交这些修改。 该隔离级别为 InnoDB 的缺省设置。
      • 解决了不可重复读问题,但是存在幻象读现象。
    • 串行化读/序列化读(SERIALIZABLE):
      • 一个事务与其他事务完全地隔离
      • 解决了所有问题,但是效率低,需要事务排队。
    • Oracle数据库默认的隔离级别是:读已提交。MySQL数据库默认的隔离级别是:可重复读。
  • 隔离级别与一致性问题的关系:

    隔离级别脏读取不可重复读幻象读
    读未提交可能可能可能
    读已提交不可能可能可能
    可重复读不可能不可能对InnDB不可能
    串行化读不可能不可能不可能
④演示事务:
  • 演示表格:

    drop table if exists t_user;
    create table t_user(
    	id int primary key auto_increment,
    	username varchar(255)
    );
    
  • 自动提交演示:

    insert into t_user(username) values('zs');
    select * from t_user;
    rollback;
    select * from t_user;
    

  • 禁用自动提交模式演示:

    start transaction;
    insert into t_user(username) values('lisi');
    select * from t_user;
    insert into t_user(username) values('wangwu');
    select * from t_user;
    rollback;
    select * from t_user;
    

    start transaction;
    insert into t_user(username) values('wangwu');
    insert into t_user(username) values('rose');
    insert into t_user(username) values('jack');
    select * from t_user;
    commit;
    select * from t_user;
    rollback;
    select * from t_user;
    

⑤设置服务器缺省隔离级别:
  • 通过修改配置文件设置:

    • 可以在 my.ini 文件中使用transaction-isolation 选项来设置服务器的缺省事务隔离级别。
    • transaction-isolation 选项可以设置的值为:
    读未提交读已提交可重复读串行化读
    READ-UNCOMMITTEDREAD-COMMITTEDREPEATABLE-READSERIALIZABLE
  • 通过命令动态设置隔离级别:

    • 隔离级别也可以在运行的服务器中动态设置,应使用 SET TRANSACTION ISOLATION LEVEL 语句。
    • 语法模式:
    SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 
    
    • 其中可以取值为:READ-UNCOMMITTED 、READ-COMMITTED 、REPEATABLE-READ、 SERIALIZABLE。
  • 隔离级别的作用范围:

    • 事务隔离级别的作用范围分为两种:全局级(对所有的会话有效)、会话级(只对当前的会话有效)。

    • 实际举例:

      • 设置会话级隔离级别为 READ COMMITTED :
      SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
      或:
      SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
      //说明默认情况下作用范围为会话级
      
      • 设置全局级隔离级别为 READ COMMITTED :
      SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
      
  • 查看隔离级别:

    • 服务器变量 tx_isolation(包括会话级和全局级两个变量)中保存着当前的会话隔离
      级别。为了查看当前隔离级别,可访问 tx_isolation 变量:

    • 实际举例:

      • 查看会话级的当前隔离级别:
       SELECt @@tx_isolation;
       或:
       SELECT @@session.tx_isolation;
      

      • 查看全局级的当前隔离级别:
       SELECT @@global.tx_isolation;
      


十六、索引 ①索引原理:

索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL 不得不首先以第一条记录开始,然后读完整个表直到它找出相关的行。表越大,花费时间越多。对于一个有序字段,可以运用二分查找(Binary Search),这就是为什么性能能得到本质上的提高。

MYISAM 和 INNODB 都是用 B+Tree 作为索引结构(主键,unique 都会默认的添加索引)

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

    • 索引就相当于一本书的目录,通过目录可以快速的找到对应的资源;主键会自动添加索引,所以尽量根据主键查询效率较高
    • 在数据库方面,查询一张表的时候有两种检索方式:
      • 第一种方式:全表扫描。
      • 第二种方式:根据索引检索(效率很高)。
  • 索引为什么可以提高检索效率呢?

    • 其实最根本的原理是缩小了扫描的范围。
    • 索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中的对象,也需要数据库不断的维护。是有维护成本的。比如,表中的数据经常被修改这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。
    • 添加索引是给某一个字段,或者说某些字段添加索引
    select ename,sal from emp where ename = 'SMITH';
    
    • 当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。
    • 当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位。
  • 什么时候需要给字段添加索引?

    • 表中该字段中的数据量庞大。
    • 经常被检索,经常出现在where 子句中的字段。
    • 经常被DML(insert、delete、update)操作的字段不建议添加索引,因为字段进行修改操作,索引也需要维护。
②索引的相关使用:
  • 创建索引对象:

    create index 索引名称 on 表名(字段名);
    
  • 删除索引对象:

    drop index 索引名称 on 表名;
    
  • 查看索引:

    show index from 表名;
    
  • 查看sql语句的执行计划:

    explain sql语句;
    
  • 案例举例:查看薪资大于1500的员工名字和薪资情况。

    //查看当前sql语句的执行计划
    explain select ename,sal from emp where sal>1500;
    

    //创建索引
    create index emp_sal_index on emp(sal);
    

    //再次查看当前sql语句的执行计划
    explain select ename,sal from emp where sal>1500;
    

③索引的分类:
  • 单一索引:给单个字段添加索引。
  • 复合索引:给多个字段联合起来添加1个索引。
  • 主键索引:主键上会自动添加索引。
  • 唯一索引:有unique约束的字段上会自动添加索引。
④索引什么时候失效?
select ename from emp where ename like '%A%';
  • 模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。

十七、视图 ①视图的基本介绍:
  • 什么是视图?

    • 站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。
    • 视图是一种根据查询(也就是 SELECt 表达式)定义的数据库对象,用于获取想要看到和使用的局部数据
    • 视图有时也被称为“虚拟表”。
    • 视图可以被用来从常规表(称为“基表”)或其他视图中查询数据。
    • 相对于从基表中直接获取数据,视图有以下好处:
      • 访问数据变得简单。
      • 可被用来对不同用户显示不同的表的内容。
  • 视图的作用:

    • 提高检索效率;隐藏表的实现细节(面向视图检索)。
    • 用来协助适配表的结构以适应前端现有的应用程序。
②视图的使用:
  • 视图的创建:

    create view 视图名 as select语句;
    //只有DQL语句才能以视图对象的方式创建出来;DQL(数据查询语言)凡是select语句都是DQL。
    
    • 注意:MySQL不支持子查询创建视图。
  • 视图的删除:

    drop view 视图名;
    
  • 视图的修改:

    alter view 视图名 as select语句;
    
  • 对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表)

  • 实际举例:

    mysql> create table emp_test as select* from emp;
    Query OK, 14 rows affected (0.04 sec)
    Records: 14  Duplicates: 0  Warnings: 0
    
    mysql> select* from emp_test;
    +-------+--------+-----------+------+------------+---------+---------+--------+
    | 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> create view myview as
        -> select empno,ename,sal from emp_test;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> select* from myview;
    +-------+--------+---------+
    | empno | ename  | sal     |
    +-------+--------+---------+
    |  7369 | SMITH  |  800.00 |
    |  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 |
    +-------+--------+---------+
    14 rows in set (0.01 sec)
    
    //通过视图修改原表数据:
    mysql> update myview set ename='Tom',sal=100
        -> where empno=7369;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select* from myview;
    +-------+--------+---------+
    | empno | ename  | sal     |
    +-------+--------+---------+
    |  7369 | Tom    |  100.00 |
    |  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 |
    +-------+--------+---------+
    14 rows in set (0.00 sec)
    
    mysql> select* from emp_test;
    +-------+--------+-----------+------+------------+---------+---------+--------+
    | EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
    +-------+--------+-----------+------+------------+---------+---------+--------+
    |  7369 | Tom    | CLERK     | 7902 | 1980-12-17 |  100.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> delete from myview where empno=7369;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select* from myview;
    +-------+--------+---------+
    | 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 |
    +-------+--------+---------+
    13 rows in set (0.00 sec)
    
    mysql> select* from emp_test;
    +-------+--------+-----------+------+------------+---------+---------+--------+
    | EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
    +-------+--------+-----------+------+------------+---------+---------+--------+
    |  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
    |  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
    |  7566 | JonES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
    |  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
    |  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
    |  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
    |  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
    |  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
    |  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
    |  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
    |  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
    |  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
    |  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
    +-------+--------+-----------+------+------------+---------+---------+--------+
    13 rows in set (0.00 sec)
    

十八、DBA命令 ①将数据库中的数据导出:
  • 导出整个库(在Windows的Dos命令窗口中执行):

    mysqldump 数据库名>存储位置 -uroot -p密码
    

  • 导出指定数据库当中的指定表(在Windows的Dos命令窗口中执行):

    mysqldump 数据库名 表名>存储位置 -uroot -p密码
    

②导入数据:
  • 登录 MYSQL 数据库管理系统之后执行:

    source sql脚本
    
    • 实际演示:
    //创建一个新的数据库
    mysql> create database demo;
    Query OK, 1 row affected (0.00 sec)
    
    //使用该数据库
    mysql> use demo;
    Database changed
    
    //导入数据
    mysql> source D:test.sql;
    Outfile disabled.
    ERROR:
    Failed to open file 'D:est.sql', error: 2
    //这里文件路径的书写有点门道,按照windows的习惯书写的话,比如我上面的t就被认为是t转义字符了,无法正常执行。解决的方法就是再加上一个,\表示的就是‘’字符了,还有一种解决方法就是使用‘/’就可以正确表示了!
    mysql> source D:\test.sql;
    ERROR:
    Unknown command '\'.
    Query OK, 0 rows affected (0.00 sec)
    ......
    mysql> show tables;
    +----------------+
    | Tables_in_demo |
    +----------------+
    | dept           |
    | emp            |
    | emp_test       |
    | myview         |
    | salgrade       |
    | t_class        |
    | t_student      |
    | t_user         |
    +----------------+
    8 rows in set (0.00 sec)
    

十九、数据库设计三范式 ①什么是设计范式?
  • 设计表的依据;按照这个三范式设计的表不会出现数据冗余。
②三范式的基本介绍:
  • 第一范式:数据库表中不能出现重复记录,每个字段是原子性的不能再分

    • 不符合第一范式的实际举例:
    学生编号学生姓名联系方式
    001张三zs@gmail.com,1359999999
    002李四ls@gmail.com,13699999999
    001王五ww@163.com,13488888888
    • 存在的问题:
      • 最后一条记录和第一条重复(不唯一,没有主键);联系方式字段可以再分,不是原子性的。
    • 改进之后:
    学生编号学生姓名Email联系电话
    001张三zs@gmail.com1359999999
    002李四ls@gmail.com13699999999
    003王五ww@163.com13488888888
    • 关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利行可能就采用一个字段了。
  • 第二范式:第二范式是建立在第一范式基础上的,另外要求所有非主键字段完全依赖主键,不能产生部分依赖

    • 不符合第二范式的实际举例:
    学生编号(主键)学生姓名教师编号(主键)教师姓名
    001张三001王老师
    002李四002赵老师
    003王五001王老师
    001张三002赵老师
    • 以上虽然确定了主键,但此表会出现大量的冗余,主要涉及到的冗余字段为“学生姓名”和“教师姓名”,出现冗余的原因在于,学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编号,而教师姓名部门依赖了主键的一个字段教师编号,这就是第二范式部分依赖。

    • 解决方案:分割为两个表格。

      • 学生信息表:
      学生编号(主键)学生姓名
      001张三
      002李四
      003王五
      • 教师信息表:
      教师编号(主键)教师姓名
      001王老师
      002赵老师
      • 学生_老师关系表:
      学生编号(主键)(外键为学生表的学生编号)教师编号(主键)(外键为教师表的教师编号)
      001001
      002002
      003001
      001002
    • 以上是一种典型的“多对多”的设计。

  • 第三范式:建立在第二范式基础上的,非主键字段不能传递依赖于主键字段。(不要产生传递依赖)

    • 不符合第三范式的实际举例:
    学生编号(主键)学生姓名班级编号班级名称
    001张三01一年一班
    002李四02一年二班
    003王五03一年三班
    004马六03一年三班
    • 从上表可以看出,班级名称字段存在冗余,因为班级名称字段没有直接依赖于主键,班级名称字段依赖于班级编号,班级编号依赖于学生编号,那么这就是传递依赖

    • 解决方案:将冗余字段单独拿出来建立表。

      • 学生信息表:
      学生编号(主键)学生姓名班级编号(外键)
      001张三01
      002李四02
      003王五03
      004马六03
      • 班级信息表:
      班级编号(主键)班级名称
      01一年一班
      02一年二班
      03一年三班
    • 以上设计是一种典型的一对多的设计,一存储在一张表中,多存储在一张表中,在多的那张表中添加外键指向一的一方的主键。

③三范式小结:
范式介绍
第一范式有主键,具有原子性,字段不可分割。
第二范式完全依赖,没有部分依赖。
第三范式没有传递依赖。
  • 数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需求。

END

个人总结:

  • 进行这一段MySQL的学习历程的原因是之前学习在学校学习过 『数据库概论』,在课堂上使用的是 Sql Server,很多公司使用MySQL,市面上的大多数教程也多是MySQL,而且学校学习偏向理论,注重底层逻辑的理解;所以想学习一下。
  • 借助的教学资料是哔哩哔哩上面黑马的教学视频(在这里感谢黑马!):MySQL基础入门到精通视频教程-MySQL数据库实战;因为有学习过理论的基础:

  • 所以我并没有通过视频进行学习,而是通过这个视频的配套资料进行笔记的编写,理解不通顺的地方再去看看视频怎么讲解的。

  • 然后就把这个教程给整完了!
  • 接下来讲讲自己对于这门教程的个人感受吧!首先就是培训机构的教程通病,过于功利性,很多东西都是浮于表面的使用,底层的机制没有讲清楚;但是因为我在学校学过这些底层的设计构建,所以能更好的构建自己的知识网络,结合一下就很好了!所以看到这一篇笔记的你们,不要止步于此,多多看看其他的数据库相关的书籍,多听百家之言,不要麻痹于这些流于表面的使用而沾沾自喜,在行业内是无法真正站住脚的!

Over!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/299651.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号