第六周学习

数据库概述

数据的分类

数据即用于描述一些客观事物的符号,这些信息都被成为数据(java中称之为属性)

  • 文本
  • 图形(图片)
  • 图像(视频)
  • 声音
  • 文件

数据库

​ 由一批数据构成的有序集合,这些数据被分门别类的存放在一些结构化的数据表里(table)里,而数据表之间又往往存在交叉引用关系,这些关系使构成的数据库被成为“关系型数据库”

非关系型数据库:数据存储在磁盘中,类似于缓存机制,表与表之间没有关联

image-20201130090721543

Mysql数据库的好处:

  • 开源免费
  • 轻量级
  • 可制作定制版

数据库的移植

将一种数据库的数据转移到另一个数据库中,比如将SQlserver中的数据转移到Mysql中就会出现数据不匹配、字段类型冲突、SQL语法不同等操作

Mysql的安装与卸载

卸载

卸载mysql数据库分为以下四个步骤

  1. 停止mysql服务
  2. 进入控制面板,卸载mysql相关的安装程序
  3. 进入mysql安装目录(C:/Program Files)删除Mysql目录
  4. 进入mysql数据目录(C:/ProgramData)删除mysql目录(重要)
安装
  • 安装
    • 可选默认路径/自定义路径
    • 可选精简版/标准版DBSM
  • 配置
    • 编码设置(gbk/utf8)
    • 密码设置

Mysql的基本命令

控制台/cmd下的命令

登录数据库/usr/local/mysql/bin/mysql -u root -p
退出数据库quit;或exit;
查看服务器状态信息\s
显示当前库select database();
查看所有实例show databases;
查看所有用户select user,host from mysql.user
修改分隔符delimiter $;
查看帮助信息\h 或 help;
创建mysql实例create database 实例名;
查看指定数据实例show create database 实例名;
使用指定实例use 实例名;
退出当前错误命令行\c
  • 登录数据库
/usr/local/mysql/bin/mysql -u root -p 
  //进入默认的数据库安装路径 
  //或者使用 mysql (-hlocalhost[数据库ip地址]) -u root -p
 /*
 本地的ip有三种形式:localhost/127.0.0.0/192.168.0.1
 */
Enter password: //输入数据库管理员密码
//成功进入数据库
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 25
Server version: 5.7.31-log MySQL Community Server (GPL)......

-h:主机地址

-u:用户名(默认root)

-p:ip地址

数据库实例和数据库

  • 数据库:所有数据表构成的大集合
  • 数据实例:数据库管理系统对数据库的一种操作方式
  • 查看mysql服务器状态信息

    \s
    
  • 查看mysql服务器中的所有实例

show databases;
  • 创建mysql实例
/*创建数据库*/
create database 数据库名;
/*创建数据库,设置默认编码格式为utf-8,设置默认排序规则是utf8_general_ci*/
create database 数据库名 set default utf8 
default collate utf_general_ci;

/*
character 设置数据库字符串格式
collate 设置字符串比较的格式
*/
  • 查看指定实例
show create database 实例名;
  • 显示当前库
select database();
  • 使用指定数据库实例
use 数据库名;
  • 退出当前错误命令,进入下一个命令行
\c
  • 显示当前所有用户
select user,host from mysql.user

%:外网可以使用当前账号访问数据库

localhost:只能本机使用该账号访问数据库

  • 显示实例下的所有表(前提先use过了)

    show tables;
    
  • 查看帮助信息

\h;
help;
  • 修改默认的分隔符

    delimiter $
    

    默认命令行结束为“;”,可以修改为指定符号结束

  • 退出sql

quit;
exit;

SQL语句入门

image-20201130170814586

sql语句分为以下几类

DDL语句

对数据库表结构进行的操作

操作代码
创建表create table
修改表alter table
删除表drop table
添加列alter table xxx add column xxx
修改列alter table xxx modify column xxx
删除列alter table xxx drop column xxx
/*创建一个表的完整语句*/
create table 表名(
	id int,name varchar(30),sex chae(2),birth date;
)
/*为表添加列*/
alter table 表名 add 列名 字段类型(字段长度);
/*删除表中指定字段*/
alter table 表名 drop column 列名;
/*设置默认值为1(下列代码有误)*/
alter table 表名 modify 指定字段 'default 1'
/*查看表中所有字段*/
show full fields from 表名;

varchar和char后要加指定长度,

名字一般会用varchar(相当于字符串),长度30左右即可

性别根据不同的字典,一般会用0、1代表男女

存在表示日期的date类型

DML 语句

数据操作语句一般用于对的语句数据库表中数据进行更新操作,比如添加,删除,修改数据等

操作代码
在表中新增数据insert into 表名(插入字段) values(第一条数据的字段集合),…,(第n条数据的字段集合);
更新表中数据update 表名 set 字段名=字段值 **where 条件;
删除表中数据delete from 表名 where 条件;,存在物理删除和逻辑删除,一般是逻辑删除

实例:

INSERT 语句

insert into 表名 (字段1,2,3...) values (对应字段名的值1,2,3...);
/*添加日期的格式是'2000-11-12',要注意月份和天数要符合实际情况
*添加字符串、字符、日期等字段的值要加''
*一次可添加多条语句,只要在一条语句后加','即可
*/

SELECT 语句

select (列名或*) from 表名 where 条件1(连接符and或or) 条件2;

UPDATE语句

/*更新语句时要注意添加where 条件*/
update 表名 set 字段名=字段值 where 条件;
/*date字段可以使用now()获取当前事件*/

DELETE语句(物理删除)

/*要注意添加where 条件*/
delete from 表名 where 条件;

逻辑删除:为某条数据添加状态status字段,一般来说1为有效数据,0为无效数据

DQL语句

数据查询语句

数据查询语句一般用于对数据库表中数据进行查询操作,命令主要包含:select

DCL语句

数据控制语句,数据控制语句一般用于对于数据库用户的权限管理,事务管理,DCL包含以下命令:

操作关键字
权限设置grant
回收权限revoke
事务提交commit
事务回滚rollback

数据库备份和导入

musqldump备份
mysqldump -uroot -p密码 数据库名or表名 > 备份文件夹路径
mysqladmin导入

从指定的sql文件恢复备份数据

先登录数据库,选择好需要导入的库,再执行导入命令,将备份的数据导入
source d:/mydb.sql

备份的数据其实是一份sql代码文件,它的第一行代码是删除相同原来的数据

drop table/database  if exists ‘数据库名/表名';

create table/database  ‘数据库名/表名'......

数据库数据类型

  • 数值类型
  • 字符类型
  • 日期时间类型
数值类型

数值类型一般分为

  • 整型

    • tinyint(M) 1
    • smallint(M) 2
    • mediumint(M) 3
    • int(M) 4
    • bigint(M): 8

    M代表该字段可以表示的长度,后面的数字是该类型可以表示的最大长度

  • 浮点型

    • flout(M,D) 4
    • double(M,D) 8
    • decimal(M,D):M

    M代表字段总长度,D代表小数点后的精度,比较精细化的浮点类型字段建议用decimal

字符串类型
  • 定长字符串 char
  • 变长字符串 varchar

char和varchar的区别

char中规定长度后,如果添加的数据长度没有占满指定长度,那么数据库会用空格自动填充剩余的长度,以保持整体长度的不变

varchar规定长度后,只是表示了最大可以存储那么长字符串,你添加了多长的字符串,它就会存储多长的字符串

  • 文件流数据格式
    • tinyblob
    • mediumblob
    • blob
    • longblob
  • 大文本格式(实际项目中会储存一些限制字数的评论)
    • tinytext
    • mediumtext
    • text
    • longtext
  • 时间格式
    • date 用格式YYYY-MM-DD表示
    • time 用格式hh:mm:ss(h大写表示24小时制)表示
    • datetime 用格式YYYY-MM-DD hh:mm:ss表示
    • timestamp 用格式YYYYMMDDhhmmss表示
    • year 用格式YYYY表示
布尔类型
  • bit 和boolean一致

作业

image-20201130192603449

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t76Zni7N-1607269187343)(/Users/zhangping/Library/Application Support/typora-user-images/image-20201130171509114.png)]

数据库的运算符

算数运算
运算符操作方式说明
+a+b加法
-a-b、或-a减法、负数
*a*b乘法
/a/b除法
%a%b取余

+的含义和java中的相同,如果是数值类型则进行加法运算,如果是’'字符串则进行字符串的拼接操作

关系运算
运算符操作方式说明
=a=b是否相等
!= ,<>a<>b是否不等
>/<a>b、a<ba是否大于/小于b
>=/<=a>=b、a<=ba是否大于/小于等于b
ina in(b1,b2,b3…)判断a是否是后续集合中的某一个
betweena between b1 and b2判断a是否在[b1,b2]范围区间内
like/not likea like/not like %b%a是否和b(部分)匹配/不匹配,使用**占位符%**表示指定字符前后存在0或多位字符
is (not) nulla is (not) nulla是否(不)为空
逻辑运算
运算符操作方式说明
and,&&a and b逻辑与,两者都为true才为true
or,||a or b逻辑或,两者都为false才会false
not,!not a逻辑非,a为ture结果为false

运算符左右需要boolean值

SQL查询

select distinct 查询列 from 表名 (inner join/left join/right jion)
单表查询
/**查询单表的所有字段**/
SELECT * FROM emp;
/**查询单表的部分字段**/
SELECT eno,ename job ,sal FROM emp;
/**函数:如果表中存在exp1字段是null的字段,则为该数据的exp1字段赋值为exp2,赋值完毕后还可以为该字段做算数运算**/
SELECT eno,ename,IFNULL(sal,0)-1500 from emp;
/**DISTINCT关键字:用于结果字段去重,下列语句含义是去除结果中job字段相同的结果**/
SELECT DISTINCT job FROM emp;
聚合函数
/**聚合函数**/
/** count(exp)统计结果数量,只会输出数据数量**/
SELECT count(*) FROM emp WHERE dno = 10;
/** sum(exp)对参数字段求和**/
SELECT SUM(sal) FROM emp WHERE sex = '男';
/** avg(exp) 求平均数**/
SELECT AVG(sal) FROM emp WHERE sex = '男';
/** max(exp) 求最大值**/
SELECT MAX(sal) FROM emp WHERE sex = '女';
/** min(exp) 求最小值**/
SELECT MIN(sal) FROM emp WHERE sex = '女';
条件查询
精确查询
/** 范围查询 **/
SELECT * FROM emp WHERE age > 40;
SELECT * FROM emp WHERE sal >=5000 or sal <= 3000;
SELECT * FROM emp WHERE sal BETWEEN 3000 AND 5000;
/** 查询符合指定的结果之一的数据 **/
SELECT * FROM emp WHERE dno = 20 or dno = 30 or dno = 40;
SELECT * FROM emp WHERE dno in(20,30,40);
/**查询所有不是经理的员工**/
SELECT * from emp WHERE job != '经理';
SELECT * FROM emp WHERE job <> '经理';
模糊查询

一般来说,实际项目不会由程序员来编写模糊查询,因为不专业的模糊查询会让程序运行速度变慢,而且会非常消耗内存

/**模糊查询**/
/**前模糊,以特结尾的数据**/
SELECT * from emp WHERE ename LIKE '%特';
/**后模糊,以阿开头的数据**/
SELECT * from emp WHERE ename LIKE '阿%';
/**前后模糊,包含卡的数据**/
SELECT * from emp WHERE ename LIKE '%卡%';
/**总共有2个字符的数据*/
SELECT * FROM emp WHERE ename LIKE '__';
/**以特结尾,而且总共有3个字符的数据*/
SELECT * FROM emp WHERE ename LIKE '__特';
分组查询
/** 分组查询 **/
/** 可以使用count来计算每个group中数据的数量**/
SELECT job ,COUNT(*) from emp GROUP BY job; 
/**查询每个部门中工资大于3500的员工,查询条件要放在分组语句前面*/
SELECT job,COUNT(*) from emp where sal > 3500 GROUP BY job
/**对分好的组进行再进行条件判断 having**/
/*.列出最低薪金大于15000的各种工作以及从事此工作的员工人数*/
SELECT job,COUNT(*)  FROM emp GROUP BY job HAVING MIN(emp.sal) > 15000;

查询语句的执行是根据查询条件一遍遍筛选,因此条件越多速度越慢,

查询排序
/** 排序 可以写在分组之前或之后,不过一般出现在sql语句的末尾**/
SELECT job,AVG(sal) from emp GROUP BY job,dno ORDER BY AVG(sal);/**不写排序后缀时,默认是升序asc*/
SELECT dno, MAX(sal) from emp WHERE job = '普通员工' GROUP BY dno ORDER BY MAX(sal) DESC;
分页查询

​ 这种分页方式是假分页:即先查出全部数据,再按条件输出有限数据项,真分页是只会查出指定条目的数据

/**限制显示数据数量,跳过x条数据 ,一页中显示数据的数量*/
limit (exp1,)exp2;
SELECT * from emp WHERE job = '普通员工' ORDER BY dno LIMIT 6,5;(从第7条数据开始显示5条数据)
多表联合查询
笛卡尔积
select * from emp,dep;

​ 指多张表的所有字段互相匹配所得出的结果,如果不设置条件限制和表间关联关系,就会出现大量的重复数据

如果A表有20条数据,B表有30条数据,则AB表的笛卡尔积就是600条数据

等值连接

​ 为笛卡尔积加上多表公有字段相等的条件

/**等值连接  条件中加上两表共有字段相等的条件*/
SELECT e.* , d.dname as '部门名',d.tel '部门电话' from emp e,dept d WHERE e.dno = d.dno;
/**查询所有员工的个人信息以及每个员工的部门名称*/
SELECT e.* ,d.dname as '部门名称' FROM emp e, dept d WHERE e.dno = d.dno;
为表和字段起别名
  • 为表起别名: 在from的表后加上指定别名既可
  • 为字段起别名: 在SELECT中跟随的字段后加上(as)别名,as可以省略

案例:三表联表查询

/**查询所有员工信息以及员工的部门名称和工资等级*/
SELECT
	e.eno,
	e.ename,
	s.LEVEL AS '工资等级',
	d.dname 
FROM
	emp e,
	dept d,
	sallevel s 
WHERE
	e.sal BETWEEN s.lowsal 
	AND s.hisal 
	AND d.dno = e.dno;
/**查询所有T8等级的员工来自哪些部门,显示部门名和员工姓名,薪资*/
SELECT
	d.dname,
	e.ename,
	s.`level` 
FROM
	emp e,
	sallevel s,
	dept d
WHERE
	e.sal BETWEEN s.lowsal AND s.hisal 
	AND s.`level` = 'T8'
	AND d.dno = e.dno;
自连接

​ 将同一个表起不同的别名,进行同一张表的互相连接

SELECT e2.* from emp e1,emp e2 where e1.dno = e2.dno and e1.ename='猪八戒';
内连接、左/右外连接
/**内连接 两表之间必须有关联字段,用inner join 和on关键字来约束*/
/**两张表中任意一张表的字段没有匹配,该数据就不会显示*/
SELECT * from emp e INNER JOIN dept d ON e.dno = d.dno;

/**左右连接,可以简单理解为,主要的表即使在副表无匹配,也会显示字段,副表相反*/
/**左连接 以关键字左边表为主去匹配右边表的字段,表之间必须有关联字段,用left join和on关键字来约束*/
SELECT * from emp e LEFT JOIN dept d ON e.dno = d.dno;
/**右连接 右表为主表*/
SELECT * from emp e RIGHT JOIN dept d ON e.dno = d.dno;	
嵌套查询、子查询
/**嵌套查询、子查询, 将一个查询的结果作为另一个查询的条件*/
/** 查询与猪八戒同一个部门的员工 **/
SELECT emp.* ,dept.dname from emp,dept WHERE emp.dno = dept.dno and emp.dno  =
		(SELECT emp.dno from emp WHERE emp.ename ='猪八戒');
/**查询在研发部和财务部的所有员工**/
SELECT * from emp WHERE emp.dno in
(SELECT dept.dno from dept WHERE dept.dname in('研发部','财务部'));
/** 查询与猪八戒同一个岗位的员工 **/
SELECT emp.* ,dept.dname FROM emp,dept WHERE  emp.dno = dept.dno and emp.job =
(SELECT job FROM emp WHERE emp.ename = '猪八戒');
/**查询行政部门中比研发中任何一个员工工资都高的员工信息*/
SELECT
	* 
FROM
	emp 
WHERE
	emp.dno = ( SELECT dept.dno FROM dept WHERE dept.dname = '行政部' ) 
AND emp.sal > ( SELECT MAX( sal ) FROM emp WHERE emp.dno = 
								( SELECT dept.dno FROM dept WHERE dept.dname = '研发部' ) )
sql语句优化
  • 避免使用子查询
  • 避免使用"*"
  • 对查询结果尽量使用limit显示
  • 尽量少用或不用like模糊查询
  • 在sql语句中尽量使用等值作为条件
  • 使用函数时尽量使用系统函数,少用自定义函数
  • 对某些经常使用或经常被查询的字段添加索引

维护数据完整性-约束

MySQL中维护数据完整性的解决方案有两种:

  1. 约束 constraint
  2. 触发器 trigger
约束 constraint
  1. 主键约束(primary key)
  2. 外键约束(foreign key)
  3. 唯一约束(unique)
  4. 检查约束(check) Mysql暂时不生效
  5. 不为空约束(not null)
主键约束(primary key)

​ MySQL中的主键可以选择任何类型,但一般是int类型,因为它可以勾选Auto Increment(自增长)属性,可以在使用sql语句添加数据时不设置主键,或设置主键为null,这样在添加数据时,数据库会自动将新增数据的主键改为上一条数据主键+1的值。一旦设置为主键,就必须满足not null条件。

insert into emp(eno,ename) values(null,'新加数据');

如果主键是varchar/字符串,java后台可以使用外部UUID生成工具包中的UUID.getUuid()方法获取不同的16/32位加密id码

  1. 注意事项:
  1. 主键列一般用于标识列(不能重复,且不为空)
  2. 尽量避免使用联合主键(设置多个列同时为主键)
  3. 任何表都应该存在主键列
外键约束(foregin key)
image-20201201162358000
  • 表名
  • 字段
  • 参考实例
  • 参考表
  • 参考字段
  • 当发生删除操作时
  • 当发生更新操作时
唯一约束(uniuqe)

唯一约束用于设置表中指定字段值是不可重复的,常见于表中用户名列、分类表中类别名类等,使用方式:

username varchar(30) unique not null

注意:实际使用中uniuqe无法查重两个肉眼看似一样的数据(比如字符串后加了空格),所以一般来说会在后台先对数据做去空格处理再保存进数据库

不为空约束(not null)

设置表中的制定字段在添加数据时必须添加值,不允许为null

检查约束(check)

检查约束在MySQL中还未生效,如果需要对字段进行检查约束,可以考虑enum类型

触发器

​ 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器是针对每一行的;对增删改非常频繁的表上切记不要使用触发器,因为它会非常消耗资源。

作业

image-20201201165856681

数据库的内置函数

  • 聚合函数
  • 字符函数
  • 数值函数
  • 日期函数
  • 加密函数
聚合函数
  • count
  • sum
  • agv
  • max
  • min
字符函数
函数解释
oncat(String[] arr)多个字符串连接成一个字符串
lenght(s)获取字符串的字节长度
case/ucase字符串转小写/转大写
ltrim(s)/rtrim(s)去除字符串左边/右边空格
Substr(s,pos,len)将字符串s从pos开始截取len长
lpad/rpad左填充/右填充

索引

索引分类
  1. 普通索引:MySQL中基本索引类型,没有限制,允许在定义索引的列中插入重复值和空值,纯粹提升查询速度

  2. 唯一性索引:索引列中的值必须是唯一的,但允许为空值

  3. 主键索引(聚簇索引):即表中主键列

  4. 全文索引:全文索引,只有在MyISAM(MySQL版本5.5之前)引擎上才能使用,只能在char、varchar、text字段上使用全文索引。

    MySQL5.5之后,引擎改用InnoDB,但依旧支持老版本引擎的部分功能

  5. 组合索引:在多个字段组合上添加索引,只有查询条件中使用了该组合中左边的字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。

如果某个字段不是常用查询条件,那么该字段就尽量不要作为索引;

添加字段索引,就是将该字段的索引添加在服务器内存中,如果索引过多会对整个服务器的运行产生巨大影响。

索引语法
image-20201202110859696
索引优点
  1. 加快检索速度
  2. 创建唯一索引,保证数据库表中每一行数据的唯一性;
  3. 加速表与表的连接
  4. 在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的实践
索引缺点
  1. 占用内存空间
  2. 针对大表创建索引耗时较长
  3. 当数据表中进行更新操作时,索引也需要更新(耗时)
索引建立的原则
  1. 不允许建立在重复率较高的字段上(如性别、职位等)
  2. 不推荐在数据量较大的表上建立
  3. 索引不要建立在经常更新的字段上

注意:

任何一张表都应该有一个索引列,默认是对主键添加索引

MySQL中的索引实现基于B+树(二叉树)最左匹配原则。

视图

视图其实是一张虚拟的表,可以通过SELECT语句创建

SELECT * from
(SELECT ename ,job,sex,age from emp)empCopy 
WHERE
empCopy.dno =20;

事务 Transaction

​ 事务是实际开发中非常常见的业务逻辑,比如转账业务,如果需要将A账户的钱转入B账户,那么这时会涉及两个修改操作:A账户前减少、B账户前增加;这两个操作要保证能同时成功或同时失败,那么这一个转账业务(涉及2个同步操作)需求/逻辑单元就成为一个事务

事务特性(※)

数据库事务包含四大特征(ACID):

  • 原子性:对于事务中的多次更新操作要么同时成功,要么同时失败
  • 一致性:保证事务操作完成后,所有结果一致
  • 隔离性:事务之间各自独立存在互不影响
  • 持久性:事务完成之后,确保所有的数据长期持久的存在
Mysql事务的使用

因为只有InnoDB引擎才能完成回滚操作,所以只有该引擎才能支持事务;MyISAM不支持事务。mysql中的事务的自动提交是默认开启的

开始事务start transaction
设置保存点名称savepoint 保存点名称
释放/删除保存点release savepoint 保存点名称
提交事务commit
事务回滚rollback
回滚到指定保存点rollback to 保存点名称
设置事务的自动提交模式set autocommit = 0(0:禁止自动提交;1:开启自动提交)

只有update操作才会产生事务,查找操作不存在事务概念

事务隔离级别

事务的并发操作可能会遇到以下问题:

  • 丢失更新:撤销A事务时,同时把B事务已提交的更新数据覆盖了

    20个线程同步访问资源,计算机随机选取一个线程允许其访问,同时为资源上锁,使其他线程无法访问

  • 脏读:事务A读取的应该是事务B更新且提交之后的数据,但此时B事务还未提交,此时A事务却可以读取到B事务更新后的数据

  • 不可重复读:事务A对此读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据的结果不一致

  • 幻读:A事务查询时,B事务做了更新操作,导致A查询的数据跟实际表中的数据不一致

隔离级别是为了防止以上问题的出现而划分出的不同级别的解决方案,mysql默认开启禁止重读权限

隔离级别(从低到高)
read uncommitted
read committed
repeatable read
serializable

存储过程

​ 存储过程,是数据库操作语言SQL的可编程实现,传统的sql语句通常是在数据库服务器中执行一条命令,命令在数据库引擎内部需要经过创建和分析的过程,因此在运行时间上开销较大;而存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析优化,并给出最终被存在系统表中的存储计划,完成后,后期只需要通过命令调用即可,因此执行过程时便可节省开销

数据库可编程性分类

  • 存储过程
  • 触发器
创建存储过程
create procedure 过程名([[IN/OUT/INOUT]参数1 类型1,参数名2 类型2 ...])

内置函数

数据库设计

数据的可编程性-触发器

​ 触发器是MySQL的对象之一,它会对插入、更新和删除操作进行监听,一旦数据库发生了插入、更新和删除操作,触发器就会自动启动

语法:

/*当指定表的某些数据(更新插入删除) 操作发生之前(之后)触发器被启动*/
create Triggle 触发器名 BEFORE/AFTER DELETE/UPDATE/INSERT ON 表名  FOR EACH ROW (为表中的每一条数据都添加触发器)
BEGIN
/*指定表的触发器被启动时,执行的操作*/
END;

案例

/*当对表执行更新操作时,将操作日志记录到表中*/
/*创建触发器*/
create trigger emp_trigger  AFTER UPDATE ON emp FOR EACH ROW
BEGIN
	INSERT INTO `logs`(id,creaTime,exqut) VALUES (NULL,now(),'UPDATE');
END;
/*更新数据,测试触发器*/
UPDATE emp SET ename = '天蓬' WHERE eno = 11;
/*删除触发器*/
DROP TRIGGER emp_trigger;

一般来说,对数据库事件的监听会由后端完成,依赖外部插件log4j

触发器的应用

​ 有主外键联系的表,如果要删除的记录主键是其他表的外键,那么就形成了外键约束,如果本数据的主键被其他表联系了,那么在删除本条数据之前(BEFROE)就要设置使用该主键作为外键的数据的外键值为null,这样才能顺利删除。

​ 如果在成功更新数据、插入数据后(AFTER)还要进行其他操作,那就需要用到AFTER关键字。

Create Trigger emp_trigger BEFORE DELETE ON dept
BEGIN
		/*删除前把有联系的外键字段置空*/
		UPDATE emp set dno = null WHERE dno = old.dno;
END;
Create Trigger emp_trigger AFTER INSERT ON vip
BEGIN
		/*插入数据后对相应的表进行修改*/
		UPDATE users set limits = 'vip' WHERE uid = new.uid;
END;	

​ 触发器针对数据库里的每一条数据,每行数据在操作前后都有对应的状态记录,old关键字表示操作之前的数据,new表示操作之后的数据,数据在触发器执行前就已经记录,即BEFORE和AFTER关键字对old和new数据源的选择不会有影响。

触发器操作类型是否存在old或new关键字
INSERT不存在old,只有new,表示(将/刚)插入的数据
UPDATEold和new都存在,old表示更新前的数据,new表示更新后的数据
DELETE不存在new,只有old,表示表示(将/刚)删除的数据

案例

/*当对数据进行删除时,将数据先备份到备份表里*/
/*创建备份表,条件部分结果绝对错误,所以只会复制表的结构,不会复制表中数据*/
CREATE TABLE emyCopsy SELECT* FROM emp WHERE 1=0;

create trigger emp_trigger2 BEFORE DELETE ON emp FOR EACH ROW
BEGIN
/*使用old关键字获取操作之前的数据*/
	INSERT INTO empCopy(eno,ename,job,hiredate,age,sex,sal,dno,createTime) VALUES(old.eno,old.ename,old.job,old.hiredate,old.age,old.sex,old.sal,old.dno,now());
END;
/*删除数据,测试触发器*/
DELETE FROM emp WHERE eno = 24;

数据库优化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66dqysKB-1607269187346)(/Users/zhangping/软帝/笔记/老师笔记/2020-12-04/笔记/assets/1596370525218.png)]

数据库设计

​ 目前主流的数据库都是关系型数据库,所以表与表之间存在不同的关联关系

表之间的关系
  • 一对一:关系(外键)建立在任意一方、或主键保持一致
  • 一对多:关系(外键)建立在多的一方(如果有多个表与A有关,那么与A有的表主动建立与A的关系)
  • 多对多:单独创建一个表来关联两个表
数据库设计范式

​ 目前关系型数据库共有六种范式

  • 第一范式 1NF:每列都是不可再分的最小数据单元
  • 第二范式 2NF:每一个非主属性都要完全依赖于主键
  • 第三范式 3NF:每一列都和主键直接相关, 除了主键外不依赖其他列
  • 巴斯-科德范式 BCNF
  • 第四范式 4NF
  • 第五范式,又称完美范式 5NF

​ 在实际开发中,一般情况只要满足三大范式即可;另外,由于程序对查询的需求(处于便捷性考虑)可能会出现违背三大范式的情况;因此三大范式只是设计数据时候的一种参考,并不是定律。

范式的存在主要解决了:

  1. 数据冗余
  2. 更新(insert,delete)操作异常
概念模型设计(ER图)

​ 概念模式是现实世界信息的抽象反映,不依赖具体的计算机系统,是现实世界到计算机世界的中间层次

实体相关概念
  • 实体:客观存在并可以相互区分的事务叫实体
  • 属性:椭圆表示,是实体所具有的某些特性
  • 主键:实体所具有的所有属性中可以唯一标识整个实体的属性集合,该集合的子集就是实体的主键
  • 实体型:具有相同特征和性质的一类实体的抽象描述
  • 实体集:矩形表示,同类型实体的集合成为实体集
  • 联系:实体与实体之间的关系(1对1、1对n、m对n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值