sadf

228 阅读36分钟

Mysql数据库

原理定义概念

定义

  • 数据库(Database)按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库
  • 数据库是长期储存在计算机内、有组织的、可共享的数据集合
  • 分类:
    • 非结构化数据:
      • 数据相对来讲没有固定的特点,这种数据非常不便于检索
      • 但是生活中很多都是非结构化数据
    • 半结构化数据
      • ·数据之间有着相同的存储结构 属性:值
      • 每一条数据的属性可以不同
        • 张三:
          • 三号学生
        • 李四:
    • 结构化数据
      • 创建在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
      • 数据之间有着相同的存储结构 属性 值
      • 同一个结构模型中每一条数据的属性都是相同的,但是值有可能不同,这些数据非常便于存储和管理。
      • 于是针对这些数据,专门设计一套数据存储的软件,现在我们说的数据库主要用来存储这些数据
  • 产品
    • image-20201221002132523转存失败,建议直接上传图片文件
    • sqlserver -->微软
    • Mysql -->Java-->Oracle收购
      • 免费
    • Oracle-->Oracle
      • 收费
    • DB2-->IBM 份额很少
  • 问题
    • 我们所有的数据库都放在软件中
    • 我们要获取到数据,就需要使用软件给我们提供的访问数据的接口
    • 最痛苦的就是程序员,我们就要为存储数据学习不同的数据库
    • 于是有人开始倡导:使用统一的操作数据库的方式
  • SQL
    • (Structured Query Language)结构化查询语言
    • 全世界所有的结构化数据库都适用
    • 分类
      • DDL
        • 数据库定义语言(定义数据库的一些组件 表 索引 视图 自增序列...)
      • DML
        • 数据库操作语言(添加 删除 修改) CRUD
      • DQL
        • 数据库查询语言 查询
      • DCL
        • 数据库控制语言(权限 用户管理...)
    • SQL语言属于第四代语言,而java c++ 才属于第三代

安装

  • 官网
  • MySql安装
    • image-20201221102008999转存失败,建议直接上传图片文件
    • image-20201221102037556转存失败,建议直接上传图片文件
    • image-20201221102132251转存失败,建议直接上传图片文件
    • image-20201221102204565转存失败,建议直接上传图片文件
    • image-20201221102216873转存失败,建议直接上传图片文件
    • image-20201221102231014转存失败,建议直接上传图片文件
    • image-20201221102301121转存失败,建议直接上传图片文件
    • image-20201221102356931转存失败,建议直接上传图片文件
    • image-20201221102414629转存失败,建议直接上传图片文件
    • image-20201221102431745转存失败,建议直接上传图片文件
    • image-20201221102452869转存失败,建议直接上传图片文件
  • 安装路径
    • C:\Program Files\MySQL\MySQL Server 8.0
    • root密码 123456
    • 端口 3306
    • 数据库已经安装完成并可以使用了,但是现在就是操作不方便
    • 进入mysql数据库的命令
      • cmd 进入到doc窗口
      • 输入 cd C:\Program Files\MySQL\MySQL Server 8.0\bin
      • mysql -u root -p
        • 输入密码 123456
      • show databases;
      • use mysql
      • select host,user from user;
  • 安装mysql的访问工具
    • navicat 收费的 ,我们需要进行简单的破解
    • 破解之前必须关闭 杀毒软件
  • 数据库连接错误
    • 1045
      • 用户名和密码不匹配 用户名root 密码 123456
    • 2003
      • 连接不到mysql服务器,很常见的是因为启动失败

概念

  • 关系模型中常用的概念:
    • 关系:可以理解为一张二维表,每个关系都具有一个关系名,就是通常说的表名
    • 元组:可以理解为二维表中的一行,在数据库中经常被称为记录
    • 属性:可以理解为二维表中的一列,在数据库中经常被称为字段
    • 域:属性的取值范围,也就是数据库中某一列的取值限制
    • 关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成
    • 关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, ... ... ,属性N),在数据库中成为表结构

scott用例表

  • emp 员工信息表
    • 表名emp
      主键empno
      字段名中文类型为空默认值其他说明
      empno雇员编号int(11)主键
      ename雇员名称varchar (255)
      job岗位工种varchar(255)
      mgr上级int(11)
      hiredate雇佣日期date
      sal工资decimal
      comm奖金|津贴decimal
      deptno部门编号int(11)外键,dept表的deptno关联
      备注
  • dept 部门信息表
    • 表名dept
      主键deptno
      字段名中文类型为空默认值其他说明
      deptno部门编号int(11)主键
      dname部门名称varchar (255)
      loc地址varchar2(255)
      备注
  • salgrade 薪资区间表
    • 表名salgrade
      主键
      字段名中文类型为空默认值其他说明
      grade等级int(11)
      losal最低int(11)
      hisal最高int(11)

SQL-DQL语句

  • 格式

    • select 列名*N from 表名 where 查询条件1 and/or 查询条件2 group by 列 Having 分组条件 Order by 排序
  • 规则

    • sql在书写的时候除了查询条件之外,大小写都可以
      • select * from user where uname ='zs';
      • SELECT * FROM USER WHERE UNAME = 'zs';
      • 保持大小写风格
      • 去公司之后需要看其他员工SQL大小写
    • -- 属于SQL语句的注释
    • 所有的查询条件为字符串时,需要用''进行修饰,否则就会当做列名去处理
  • select查询列和别名

    • --查询所有员工信息(*通配符,默认查询所有的列)
      select * from emp;
      --查询员工的姓名
      select ename from emp;
      --查询员工的薪资
      select sal from emp;
      --查询员工的姓名和薪资
      select ename , sal from emp;
      select ename sal from emp;
      select ename sal comm from emp;
      --查询员工的姓名和薪资,推荐使用单引号
      select ename '员工姓名', sal "薪资" from emp;
      --查询到的数据可以直接进行运算
      select ename ,sal ,sal * 12 from emp;
      select ename ,sal ,comm ,(sal+comm) * 12 from emp;
      
  • select的条件查询

    • 普通条件查询 = > < != <> >= <=

      • --查询员工编号为7369的员工
        select ename,sal from emp where empno = 7369;
        --查询员工姓名叫做SMITH
        select ename,deptno,job from emp where ename = &#39;SMITH&#39;;
        select ename,deptno,job from emp where ename = &#39;smith&#39;;
        --查询薪资大于2000的员工姓名
        select ename from emp where sal &gt; 2000;
        --查询工作为SALESMAN
        select * from emp where job = &#39;SALESMAN&#39;;
        --查询部门在20的员工
        select * from emp where deptno = 20;
        --查询薪资不等于2000的员工
        select * from emp where sal != 2000;
        select * from emp where sal != 2000;
        
    • in 在某个范围中查找

      • --查询 员工编号为 7369 7788 7881的员工信息
        select * from emp where empno in (7369,7788,7881);
        --查询 员工编号除了 7369 7788 7881之外的所有员工信息
        select * from emp where empno not in(7369,7788,7881);
        --查询除了10,20部门之外的所有员工
        select * from emp where deptno not in (10,20);
        
    • null值查询

      • --查询不发放津贴的员工信息
        select * from emp where comm is null;
        --查询发放津贴的员工信息
        select * from emp where comm is not null;
        
    • 范围比较

      • --查询薪资范围在1000-4000之间的员工信息 [1000.4000]
        select * from emp where sal between 1000 and 4000;
        
    • 模糊查询 % _

      • --查询名字中有S的员工
        select * from emp where ename like '%S%';
        --查询名字最后一个字符是S
        select * from emp where ename like '%S';
        --查询名字第一个字符是S
        select * from emp where ename like 'S%';
        --查询名字第二个字符是A
        select * from emp where ename like '_A%';
        --查询名字中有%的员工
        select * from emp where ename like '%\%%';
        
        --查询名字第8 188个字符是A,这是需要一些特殊的手段-》函数
        -- % 代表任意字符的任意次数 _任意字符的一次
        
    • 多条件联合查询 and or

      • and 必须前后同时满足条件才能返回结果

      • or前后有一个满足条件就能返回结果

      • --查询在20部门并且薪资大于2000的员工
        select * from emp where deptno =20 and sal >2000;
        --查询在20部门或者薪资大于2000的员工
        select * from emp where deptno = 20 or sal >2000;
        --查询不在20部门并且薪资小于2000的员工
        select * from emp where deptno <> 20 and sal <2000;
        
  • select结果排序 order by

    • 使用asc是升序排列(默认),使用desc可以降序排序

    • 单列

      • --按照薪资进行排序(默认升序)
        select * from emp order by sal;
        --按照薪资进行排序(降序)
        select * from emp order by sal desc;
        --按照薪资进行排序(升序)
        select * from emp order by sal asc;
        --按照津贴进行排序(null排在最前面)
        select * from emp order by comm;
        
    • 多列

      • --多个排序的列
        select * from emp order by deptno,sal;
        --多个排序的列(部门升序 薪资降序)
        select * from emp order by deptno,sal desc;
        --多个排序的列(工作,薪资)
        select * from emp order by job,sal;
        
  • select结果分页

    •   --每次查询前N行
        SELECT
        	* 
        FROM
        	emp 
        	LIMIT 4;
        	
        --查询第N页,每页显示M个
        select * from emp limit 0,3;
        select * from emp limit 3,3;
        select * from emp limit 6,3;
        select * from emp limit (n-1)*M,M;
        
        --查询薪资大于1000的逆序排列,然后显示前5条记录
        select * from emp where sal >1000 order by sal desc limit 0,5 ;
      
  • SQL语句错误

    • select enane from emp

      1054 - Unknown column 'enane' in 'field list'

      将来出现错误的时候,直接将错误编号输入到百度查询即可

单行函数

  • 函数都是数据库提前给我们准备好的,所以我们可以直接调用,使用函数可以让指定的列计算出我们需要的数据
  • 单行函数
    • 指的是操作一行数据返回一行数据,操作10行数据返回10行数据

    • 字符串函数

      • image-20201222093644013转存失败,建议直接上传图片文件

      • -- 长度
          - select ename,length(ename) from emp;
        -- 截取
          - select ename,SUBSTR(ename,1,3) from emp;
          - select * from emp where substr(ename,5,1)='S';
        -- 大小写
          - select ename, upper(ename),lower(ename) from emp;
        -- 拼接
          - select CONCAT(empno,'=',ename) from emp;
        -- 替换
          - select ename,REPLACE(ename,'T','—') from emp;
        
    • 日期函数

      • image-20201222093713961转存失败,建议直接上传图片文件

      • -- 获取当前系统时间
          - select hiredate,sysdate() from emp;
          - select hiredate,CURRENT_DATE(),CURRENT_TIME(),CURRENT_TIMESTAMP() from emp;
        -- 日期转换
          - select DATE_FORMAT(sysdate(),'%Y-%m-%d %H:%i:%s')
          - select hiredate, date_format(now(),'%Y年%m月%d日 %H时%i分%s秒') from emp;
        -- 分别获取 年月日 时分秒 星期
          - select  
            - SECOND MINUTE HOUR DAY WEEK MONTH YEAR
        -- 日期的加减操作
          - select hiredate,ADDDATE(hiredate,9),ADDDATE(hiredate,-9) from emp;
          - select DATE('2012-11-11') ;
        
    • 数字函数

      • image-20201222093627890转存失败,建议直接上传图片文件

      • -- 向上取整 向下取整
          - select ceil(12,1),floor(12.9) 
        -- mod abs pow PI rand round TRUNCATE(直接进行截取,不进行四舍五入)
        -- 保留多少位有效数字
          - select round(1.4999999,2),round(1.4999999),round(1.4999999,-1)
          - select TRUNCATE(1.4999999,2)
        
    • 转换函数

      • -- 日期--》字符串
          - date_format(date,expr)
          - select DATE_FORMAT(sysdate(),'%Y-%m-%d %H:%i:%s');
        -- 字符串--》日期
          - 要注意字符串和格式的匹配
          - select STR_TO_DATE('2020-4-16 17:15:24','%Y-%c-%d %H:%i:%s');
        -- 数字--》字符串
          - 直接拼接一个字符串即可,可以自动转换
        -- 字符串--》数字
          - 依靠函数提供的参数
        
    • 其他函数

      • 空值的处理
        • ifnull(exp1,exp2) exp1!=null?exp1:exp2
        • select IFNULL(comm,888) from emp;
      • 加密算法
        • select MD5('123456');
        • select AES_ENCRYPT('123456','abcd'),AES_DECRYPT(AES_ENCRYPT('123456','abcd'),'abcd');

多行函数

  • image-20201221004912874转存失败,建议直接上传图片文件
  • 不管函数处理多少条,只返回一条记录
  • 如果你的数据可以分为多个组,那么返回的数据条数和组数相同
    • 每个部门的平均薪资
    • 10 20 30 --》3
  • 常用的多行函数有5个
    • max 最大值
      • 如果处理的值是字符串,将会把值按照字典序排序
    • min 最小值
      • 如果处理的值是字符串,将会把值按照字典序排序
    • avg 平均值
      • 只能用于数值型数据,求平均值
    • sum 求和
      • 如果求和过程中有null,那么不会计算在内
    • count 求总数
      • 如果统计的数据中有null,不会把null统计在内
  • 经典的错误
    • --查询公司最低薪资的员工是谁?
    • select min(sal) ,ename from emp;
      • mysql语法可行
      • oracle不可行
    • 将来工作的时候不能把普通列和组函数写在一起
      • 虽然mysql语法不会报错,但是给的结果是错误的

数据分组

  • 按照某一个条件进行分组,每一组返回对应的结果

  • group by 可以对指定的列进行分组,列尽量有相同的

  • having可以对分组之后的数据进行过滤,所以能出现在having中的比较项一定是被分组的列或者是组函数

  • 底层

    • where称之为行级过滤,处理的是表中每一行数据的过滤
    • having称之为组级过滤,处理的是分组之后的每一组数据
    • 能使用where的,尽量不要使用having
  • --查询每种工作的平均薪资
    select job,avg(sal) from emp group by job;
    --查询每个部门的最高薪资和最低薪资
    select max(sal),min(sal) from emp;
    select deptno,max(sal),min(sal) from emp group by deptno;
    --查询每个部门的人数和每月工资总数
    select deptno,count(empno),sum(sal) from emp group by deptno;
    
    --查询每个部门,每种工作的平均薪资
    select deptno,job , avg(sal) from emp group by deptno,job;
    select deptno,job , avg(sal) from emp group by deptno,job order by depto ,job;
    
    --查询个人姓名的平均薪资--尽量对多数据进行分组
    select ename, max(sal),min(sal) from emp group by ename;
    
  • --查询平均薪资高于2500的部门
    select deptno,avg(sal) from emp group by deptno having avg(sal)>=2500;
    select deptno,avg(sal) from emp group by deptno having ename like '%A%';
    
    --查询20部门的平均薪资
    select deptno,avg(sal) from emp group by deptno having deptno = 20;
    select deptno,avg(sal) from emp where deptno = 20 group by deptno;
    
  • --查询10 20部门中,并且在二月份入职员工中,每个部门中平均薪资高于1500的工作是什么,并按照部门,工作平均薪资进行排序
    select * from emp where deptno in (10,20) ;
    select deptno ,job ,avg(sal) from emp where deptno in (10,20) group by deptno ,job having avg(sal)>1500 ;
    select deptno ,job ,avg(sal) from emp where deptno in (10,20) group by deptno ,job having avg(sal)>1500 order by deptno ,avg(sal) ;
    --美观写法
    SELECT
    	deptno,
    	job,
    	avg( sal ) '平均薪资'
    FROM
    	emp 
    WHERE
    	deptno IN ( 10, 20 ) 
    GROUP BY
    	deptno,
    	job 
    HAVING
    	avg( sal )> 1500 
    ORDER BY
    	deptno,
    	avg( sal );
    

DQL单表关键字执行顺序

  • select
    • 我们要显示那些列的数据
  • from
    • 从那张表中获取数据
  • where
    • 从表中获取数据的时候进行行级的数据过滤
  • group by
    • 对数据进行分组处理,一组获取对应的结果
  • having
    • 组级过滤,组级过滤的数据必须是分组条件或者是组函数
  • order by
    • 排序
    • asc desc
  • 执行的顺序
    • from --> where -->group by -->having-->select -->order by

多表查询

  • 查询的两张表如果出现同名的列,我们需要将表名标注到列名前面

  • 如果是非同名的列,表名可加可不加,推荐加上

    • 为了书写方便,可以给表添加别名
    • 一般情况下取首字母,特殊情况下取它所代表的含义
    • 表的别名只在本次查询中生效
  • 如果表与表进行关联查询的时候,如果不添加关联条件,查询的总记录数就是a*b = 笛卡尔积

    • a 15 b 10 c 10 -->1500条
  • 多表查询的时候必须要加条件

    • 等值
    • 非等值
  • --查询每个员工所在的部门名称
    select ename,deptno from emp;
    select deptno,dname from dept;
    select emp.ename,emp.deptno,dept.deptno,dept.dname from emp , dept;
    --等值关联查询
    select emp.ename,emp.deptno,dept.deptno,dept.dname from emp , dept where emp.deptno = dept.deptno;
    select emp.ename,dept.dname from emp , dept where emp.deptno = dept.deptno;
    --添加别名
    select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno;
    

表与表关联的方式

  • 因为表的关联条件和业务查询条件放在了一起,为了防止混淆于是提供了下面三种方式

  • 自然连接

    • 会自动选择列名相同并且类型相同的列

    • --查询薪资大于2000的员工姓名和部门名称
      select e.ename,d.dname from emp e ,dept d where e.deptno = d.deptno and e.sal >2000;
      --自然连接
      select e.ename,d.dname from emp e natural join dept d ;
      select e.ename,d.dname from emp e natural join dept d where e.sal > 2000 ;
      
  • using

    • 不需要mysql帮我们选择等值连接的列,现在我们指定等值连接的列

    • ----查询薪资大于2000的员工姓名和部门名称 using
      select e.ename,d.dname from emp e join dept d using(deptno);
      select e.ename,d.dname from emp e join dept d using(deptno) where e.sal > 2000;
      
  • on

    • 我们可以指定两张表关联的条件,可以是非等值的操作

    • ----查询薪资大于2000的员工姓名和部门名称 using
      select e.ename,d.dname from emp e join dept d on(e.deptno = d.deptno);
      select e.ename,d.dname from emp e join dept d on(e.deptno = d.deptno) where e.sal > 2000;
      --查询每个员工所对应的薪资登记
      select e.ename,s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal;
      select e.ename,s.grade from emp e join salgrade s on(e.sal between s.losal and s.hisal);
      
  • 查询名字中带有A字母的员工姓名,部门名称和薪资等级

    • SELECT
      	e.ename,
      	d.dname,
      	s.grade 
      FROM
      	emp e,
      	dept d,
      	salgrade s 
      WHERE
      	e.deptno = d.deptno 
      	AND e.sal BETWEEN s.losal AND s.hisal 
      	AND e.ename LIKE '%A%';
      -----------------------------------------
      SELECT
      	e.ename,
      	d.dname,
      	s.grade 
      FROM
      	emp e
      	JOIN dept d USING ( deptno )
      	JOIN salgrade s ON (e.sal BETWEEN s.losal AND s.hisal)
      WHERE
      	e.ename LIKE '%A%';
      

表与表的外连接

  • 当我们对两张表进行关联查询的时候,基于数据的原因导致其中一张表中的数据没办法被完全查询出来

  • 外连接可以让没查询出来的数据也显示出来

  • 因为我们写SQL的时候表总有左右之分 ,外连接也分为

    • 左外连接:显示左面表所有的数据
    • 右外连接:显示右面表所有的数据
  • --统计每个部门的人数
    select deptno,count(empno) from emp group by deptno ;
    select * from emp e join dept d using(deptno);
    select * from emp e left join dept d using(deptno);
    select * from emp e right join dept d using(deptno);
    
    
    select deptno,count(e.empno) from emp e right join dept d using(deptno) group by deptno;
    
    -------------------------全外连接
    SELECT
    	deptno,
    	e.ename,
    	d.dname 
    FROM
    	emp e RIGHT JOIN dept d USING ( deptno ) 
    UNION
    SELECT
    	deptno,
    	e.ename,
    	d.dname 
    FROM
    	emp e LEFT JOIN dept d USING ( deptno );
    	
    -------------------------Oracle的全外连接使用 Full Join
    	
    

表与表的自连接

  • 我们要查询的两个字段同时处于一张表上,我们只能将一张表当做含有不同意义的两张表去处理

  • 给相同的表取不同的简称(按照所代表的含义去取)

  • --查询每个员工与其直属领导的名字
    select e.ename,m.ename from emp e,emp m where e.mgr = m.empno;
    select e.ename,m.ename from emp e join emp m on(e.mgr = m.empno); 
    

表与表的子连接

  • 把一个SQL语句的查询结果当成另外一个SQL语句的查询条件

  • --查询公司中薪资最低的员工姓名
    select ename,sal from emp where sal = (select min(sal) from emp);
    --查询公司中谁的薪资高于平均薪资
    select ename,sal from emp where sal > (select avg(sal) from emp);
    
    --谁的薪资高于20部门员工的薪资
    select ename,sal from emp where sal > all(select sal from emp where deptno = 20 );
    select ename,sal from emp where sal > some(select sal from emp where deptno = 20 );
    select ename,sal from emp where sal in (select sal from emp where deptno = 20 );
    

表与表的伪表查询

  • 如果我们所需要的查询条件 需要别的SQL语句提供

  • 如果只需要一个条件 那么可以使用子查询来完成

  • 如果需要多个查询条件,这是就要将所有的查询结果当做伪表进行管理

  • 我们需要把一些含有特殊符号的列名设置别名,然后给伪表设置一个别名(见名知意)

  • --查询高于自己部门平均薪资的员工信息
    select deptno,avg(sal) avgsal from emp group by deptno ;
    
    SELECT
    	e.ename,
    	e.sal,
    	e.deptno 
    FROM
    	emp e,
    	( SELECT deptno, avg( sal ) avgsal FROM emp GROUP BY deptno ) d 
    WHERE
    	e.deptno = d.deptno 
    	AND e.sal > d.avgsal;
    

SQL-DML

SQL-DML插入

  • insert into 表名 values();
    • insert into dept values(50,'sxt','shanghai');
    • 要求插入数据的数量,类型要和定义的表结构一致
      • insert into dept values(50,'sxt','shanghai','liyi');
      • insert into dept values(50,'sxt');
      • insert into dept values('abcd',50.'sh');
  • insert into 表名(列名) values(值...);
    • insert into emp(empno,ename,deptno) values(6666,'ly',50);
    • 要求插入数据的数量顺序和表名后的列要一致
  • insert into 表名(列名) select ....
    • create table dp as select * from dept where 1<>1;
    • insert into dept(deptno,dname) select empno ,ename from emp;

SQL-DML删除

  • delete from 表名
    • delete from dept;
  • delete from 表名 where 条件
    • delete from emp where comm is null;
  • 这属于一种物理删除,删完之后理论上不能再找回
  • truncate table emp;
    • 截断表--不要使用--不要使用

SQL-DML修改

  • update 表名 set 列名=value ,列名=value
    • update salgrade set losal = 888 ,hisal = 999;
  • update 表名 set 列名=value ,列名=value where 条件
    • update salgrade set losal = 666 ,hisal = 1888 where grade = 3;

数据库事务

  • 数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成
  • 事务指的是数据库一种保护数据的方式
  • 事务一般由增删改操作自动调用,事务根据数据库不同提交的时机也是不同的
    • mysql数据库默认执行增删改就会提交事务
    • 我们可以设置为 手动提交 begin 或者 start transaction;
  • 事务的特征
    • ACID原则
    • 原子性
      • 事务是操作数据的最小单元,不可以再分
    • 一致性
      • 事务提交之后,整个数据库所看到数据都是最新的数据
      • 所有人看到的数据都是一致的
    • 隔离性
      • 别人无法访问到我们未提交的数据,而且一旦这个数据被我修改,别人也无法进行操作
    • 持久性
      • 事务一旦被提交,数据库就进入到一个全新的状态
      • 数据在也不能返回到上一个状态
  • 事务如何开启和提交?
    • 开启
      • 当我们执行增删改操作的时候就会默认开启一个事务
      • 这个事务和当前操作的窗口有关,别人是无法共享这个事务的
    • 提交
      • 手动
        • 显示
          • commit; 提交
          • rollback; 回滚
        • 隐式
          • 执行DDL操作,会默认提交当前的事务
          • 用户退出,事务统一进行回滚(Mysql)
      • 自动
        • mysql数据库执行DML操作之后会自动的提交事务
        • 好处:
          • 方便
        • 坏处:
          • 不能将多个SQL纳入到一个事务,不便于管理
          • 当我们大批量插入数据的时候,数据库会频繁的开启关闭事务影响插入效率

事务的隔离级别

  • 根据数据库的不同用途,我们可以对数据库的事务进行级别的设置

  • 级别设置的越高,数据越安全,但是效率越低

    • 读未提交
      • 我们可以读取到别人未提交的数据
      • 有可能产生脏读的问题
    • 读已提交
      • 只能读取别人提交后的数据
      • 不能达到可重复读,但是可以避免脏读
      • 有可能产生虚读或者幻读的情况
    • 可重复读
      • 当数据被我查询之后,别人就不能修改这个数据了
      • 说明在我查询的时候已经有事务操作到这些数据,查询都会开启事务
      • 但是不能防止别人查询别的数据
    • 序列化
      • 当前数据库只能存在一个事务,但我操作数据库的时候,别人是不能访问数据库的
      • 这时对于用户来讲数据相当安全,一般在倒库的时候才会开启这种级别
  • 脏读

    • 读取别人未提交的数据,这个数据是不安全的
  • 虚读

    • 第一次读取的数据,第二次在读取的时候有可能被被人修改了
  • 幻读

    • 第一次读取的数据,第二次多了一条或者少了一条

SQL-DDL

常见组成

  • 库的操作
  • 视图
  • 存储过程
  • 事件
  • 索引
  • 触发器

数据库的操作

  • # 数据库创建
    create database 数据库名 charset utf8;
    
    # 查看数据库
    show databases;
    show create database db;
    select database();
    
    # 选择数据库
    use 数据库名
    
    # 删除数据库
    drop database 数据库名;
    
    # 修改数据库
    alter database db1 charset utf8;
    

数据类型

  • image-20201221010419365转存失败,建议直接上传图片文件

  • image-20201221010452597转存失败,建议直接上传图片文件

  • image-20201221010437043转存失败,建议直接上传图片文件

表 table的创建

-- 我们首先要对你操作的数据有一个基础型的了解
-- 学号 姓名 性别 出生日期 入学时间 专业 院系 创建时间 
-- 学号 int 姓名 varchar 性别 char 出生日期 date 入学时间 date 专业 varchar 院系 varchar 创建时间 timestamp

create table t_student(
    sno int,
    sname varchar(40),
    gender char(1),
    birthday date,
    schooltime date,
    major varchar(255),
    department varchar(255),
    createtime timestamp 
);

表 table的修改

--根据查询语句创建表
CREATE TABLE STU01 AS SELECT * FROM t_student;
--添加一列
alter table t_student add updatetime timestamp default now();
--删除一列
alter table t_student drop column email;
--修改一列
alter table t_student modify major varchar(20);
--修改列名
alter table t_student rename COLUMN birthday to birth;
--修改表名
rename t_student to t_s;
--删除一张表
drop table t_s;

表 table的约束

  • 约束指的是我们创建的表 别人在插入数据的时候,对数据的约束,而不是对创建人的约束

  • 主键约束 PRIMARY KEY

    • 主键值必须唯一标识表中的每一行,且不能为 NULL,即表中不可能存在有相同主键值的两行数据。

    • 主键分为单字段主键和多字段联合主键

    • 联合主键不能包含不必要的多余字段。当把联合主键的某一字段删除后,如果剩下的字段构成的主键仍然满足唯一性原则,那么这个联合主键是不正确的。这是最小化原则。

    • CREATE TABLE t_pk01(
      id INT(11) PRIMARY KEY,
      name VARCHAR(25),
      deptId INT(11),
      salary FLOAT
      );
      
      CREATE TABLE t_pk03(
      tid INT(11),
      cid INT(11),
      salary FLOAT,
      PRIMARY KEY(tid,cid)
      );
      
      CREATE TABLE t_pk02(
      id VARCHAR(40),
      name VARCHAR(25),
      salary FLOAT
      );
      
      -- ALTER TABLE <数据表名> ADD PRIMARY KEY(<字段名>);
      ALTER TABLE t_pk02 ADD PRIMARY KEY(id);
      
      -- ALTER TABLE <数据表名> DROP PRIMARY KEY;
      ALTER TABLE t_pk04 DROP PRIMARY KEY;
      
  • 唯一性约束 unique

    • 列中的值可以为空但是不能相同

    • CREATE TABLE tb_unique01(
      id INT(11) PRIMARY KEY,
      name VARCHAR(22),
      phonenum VARCHAR(11) UNIQUE,
      location VARCHAR(50)
      );
      
      -- ALTER TABLE <数据表名> ADD CONSTRAINT <唯一约束名> UNIQUE(<列名>);
      ALTER TABLE tb_unique01 ADD CONSTRAINT t_unique01_unique_location UNIQUE(location);
      
      -- ALTER TABLE <表名> DROP INDEX <唯一约束名>;
      ALTER TABLE tb_unique01 DROP INDEX unique_t_unique01_location;
      
  • 非空约束 not null

    • 列中的值不能为null

    • CREATE TABLE tb_null01(
      id INT(11) PRIMARY KEY,
      name VARCHAR(22) NOT NULL,
      location VARCHAR(50)
      );
      
      -- ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <字段名> <数据类型> NOT NULL;
      ALTER TABLE tb_null01 CHANGE COLUMN location location VARCHAR(50) NOT NULL;
      
      -- ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <字段名> <数据类型> NULL;
      ALTER TABLE tb_null01 CHANGE COLUMN location location VARCHAR(50) NULL;
      
  • 外键约束

    • 定义外键时,需要遵守下列规则:

      • 主表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
      • 必须为主表定义主键。
      • 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。
      • 在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或唯一性键。
      • 外键中列的数目必须和主表的主键中列的数目相同。
      • 外键中列的数据类型必须和主表主键中对应列的数据类型相同。
    • 外键的删除

      • 级联删除
        • 设置为NULL
        • 阻止删除
        • 删除主表数据的时候,要保证这个ID没有被字表所使用
    • --1位老师对应N个学生 teacher表为主表,student表为外键表  tid为外键
      create table teacher(
          tid varchar(40) primary key,
      	name varchar(40)
      );
      create table student(
          sid varchar(40) primary key,
      	name varchar(40),
          tid varchar(40),
          CONSTRAINT fk_teacher_student_tid FOREIGN KEY(tid) REFERENCES teacher(tid) on delete cascade
      );
      
      
      insert into teacher values('a','岳不群');
      insert into teacher values('b','定闲师太');
      insert into teacher values('c','无崖子');
      
      insert into student values('1','令狐冲','a');
      insert into student values('2','岳灵珊','a');
      insert into student values('3','依琳','b');
      insert into student values('4','星宿大仙','c');
      --错误数据,因为主表主键没有d
      insert into student values('5','任我行','d');
      
      -- 修改表
      ALTER TABLE <数据表名> ADD CONSTRAINT <外键名> FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
      
  • 约束回顾

    • -- 查看表中的约束
      SHOW CREATE TABLE <数据表名>;
      
      create table table_name(
      列名1 数据类型 (int) primary key auto_increment,
      列名2 数据类型  not null,
      列名3 数据类型   unique,
      列名4 数据类型  default '值',
      constraint  索引名 foreign key(外键列)  references 主键表(主键列) on delete cascade | on delete set null
      )
      
      1.主键约束
      添加:alter table table_name add primary key (字段)
      删除:alter table table_name drop primary key
      2.非空约束
      添加:alter  table table_name modify 列名 数据类型  not null 
      删除:alter table table_name modify 列名 数据类型 null
      3.唯一约束
      添加:alter table table_name add unique 约束名(字段)
      删除:alter table table_name drop key 约束名
      4.自动增长
      添加:alter table table_name  modify 列名 int  auto_increment
      删除:alter table table_name modify 列名 int  
      5.外键约束
      添加:alter table table_name add constraint 约束名 foreign key(外键列) 
      references 主键表(主键列)
      
      
      删除:
      第一步:删除外键
      alter table table_name drop foreign key 约束名
      
      6.默认值
      添加:alter table table_name alter 列名  set default '值'
      删除:alter table table_name alter 列名  drop default
      

索引

  • 假如我们有一张表有1000万条记录,现在查询ename = ‘zs’的员工信息

    • 原始的数据遍历
    • 让我们查询的数据有序:可以使用折半查找法
  • image-20201223162613455转存失败,建议直接上传图片文件
  • 案例

    • 拼音
    • 偏旁部首
  • 简介

    • 在MySQL中,索引(index)也叫做“键(key)”,它是存储引擎用于快速找到记录的一种数据结构。

    • 索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对性能的影响就愈发重要。

    • 索引优化应该是对查询性能优化最有效的手段。

    • -- CREATE INDEX indexName ON mytable(username); 
      Create Index index_dept_dname on dept(dname);
      Drop  Index index_dept_dname on dept;
      
    • image-20201223163555797转存失败,建议直接上传图片文件

  • 索引的分类

    • 常规索引
      • 常规索引,也叫普通索引(index或key),它可以常规地提高查询效率。一张数据表中可以有多个常规索引。常规索引是使用最普遍的索引类型,如果没有明确指明索引的类型,我们所说的索引都是指常规索引。
    • 主键索引
      • 主键索引(Primary Key),也简称主键。它可以提高查询效率,并提供唯一性约束。一张表中只能有一个主键。被标志为自动增长的字段一定是主键,但主键不一定是自动增长。一般把主键定义在无意义的字段上(如:编号),主键的数据类型最好是数值。
    • 唯一索引
      • 唯一索引(Unique Key),可以提高查询效率,并提供唯一性约束。一张表中可以有多个唯一索引。
    • 外键索引
      • 外键索引(Foreign Key),简称外键,它可以提高查询效率,外键会自动和对应的其他表的主键关联。外键的主要作用是保证记录的一致性和完整性。
  • 索引是数据库中一块独立的空间,专门存储索引值的一刻B-树

    • 我们可以通过B树快速的定位到要查找的数据
    • 尽量不要对重复列添加索引
      • 性别
    • 优点
      • 索引可以让MySQL快速地查找到我们所需要的数据,但这并不是索引的唯一作用。
        • 索引大大减少了MySQL服务器需要扫描的数据量。
        • 索引可以帮助服务器避免排序和临时表。
        • 索引可以将随机I/O变为顺序I/O。
    • 缺点
      • 影响数据库的增删改速度

视图

  • 简介

    • MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中。
    • 行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的。
  • 优点

      1. 定制用户数据,聚焦特定的数据
      1. 简化数据操作
      1. 提高数据的安全性
      1. 共享所需数据
      1. 更改数据格式
      1. 重用 SQL 语句
  • 创建 查看

    • -- CREATE VIEW <视图名> AS <SELECT语句>
      -- <视图名>:指定视图的名称。该名称在数据库中必须是唯一的,不能与其他表或视图同名。
      -- <SELECT语句>:指定创建视图的 SELECT 语句,可用于查询多个基础表或源视图。
      
      CREATE VIEW v_swordsman AS 
      ( SELECT tid, NAME FROM teacher ) UNION ALL
      ( SELECT sid, NAME FROM student );
      
      SELECT
      	* 
      FROM
      	v_swordsman
      
      -- DESCRIBE 视图名;
      DESCRIBE v_swordsman
      
      -- SHOW CREATE VIEW 视图名;
      SHOW CREATE VIEW v_swordsman
      
      -- ALTER VIEW <视图名> AS <SELECT语句>
      -- <视图名>:指定视图的名称。该名称在数据库中必须是唯一的,不能与其他表或视图同名。
      -- <SELECT 语句>:指定创建视图的 SELECT 语句,可用于查询多个基础表或源视图。
      
      --DROP VIEW IF EXISTS <视图名1> [ , <视图名2> …]
      

三范式

  • 我们创建表需要遵循的规范

  • 第一范式

    • 数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组

      • IDnameAddress
        1迪丽热巴新疆-乌鲁木齐
        2黄晓明山东-青岛
        3黄渤山东-青岛
      • IDnameprovincecity
        1迪丽热巴新疆乌鲁木齐
        2黄晓明山东青岛
        3黄渤山东青岛
  • 第二范式

    • 数据库中每一行数据必须依赖于主键,每一个行数据都要有主键

    • 主键是一行数据的唯一性标识

    • IDnameprovincecitygood
      1迪丽热巴新疆乌鲁木齐葡萄干
      2黄晓明山东青岛啤酒
      3黄渤山东青岛啤酒
    • idsnametidtname
      1张翠山3灭绝
      2宋远桥1张三丰
      3令狐冲2岳不群
  • 第三范式

    • 表中非主键的列要完全依赖于主键,不能出现部分属性依赖于其他属性

    • 当出现传递依赖的时候要将非依赖于主键的列专门创建一张表进行管理

    • idsnametid
      1张翠山1
      2宋远桥1
      3令狐冲2
    • tidtname
      3灭绝
      1张三丰
      2岳不群

表与表的关系

  • 但是为了维护两张表的关系,然后根据两张表的对应关系可以分为:
    • 1:1-->
      • 两张表中的数据 1条只和1条对应
      • 关联方案
        • 让关联数据主键值相同
        • 在一张表中存放另外一张表的主键
      • image-20201223122015875转存失败,建议直接上传图片文件
      • image-20201223122057267转存失败,建议直接上传图片文件
    • 1:N-->
      • A表中的一条数据有可能对应B表中的多条记录
      • 1老师:N学生
      • 关联方案
        • 在N方的表中设计一个1方的主键列,也称之为外键关联
      • image-20201223121927173转存失败,建议直接上传图片文件
    • N:N-->
      • A表中的一条数据有可能对应B表中的多条记录
      • 同时B表中的一条数据有可能对应A表中的多条记录
      • 1学生:N课程
      • 1课程:N学生
      • 关联方案
        • s学生表 c课程表
        • 一般都会创建第三章表专门管理学生与课程的关系
          • sid,cid 作为联合主键管理信息
          • id ,sid ,cid 以ID作为这张表的单独主键
      • image-20201223121948644转存失败,建议直接上传图片文件

存储过程

创建调用删除

  • --删除存储过程
    drop procedure if exists p_hello_world;
    
    --创建存储过程
    create procedure p_hello_world()
    begin
        select sysdate();
    end;
    
    -- 调用存储过程
    call p_hello_world();
    
  • --删除存储过程
    drop procedure if exists p_hello_world;
    
    --创建存储过程
    create procedure p_hello_world(in v_empno int)
    begin
        select * from emp e where e.empno = v_empno;
    end;
    
    -- 调用存储过程
    call p_hello_world(7788);
    

变量定义与赋值

  • --删除存储过程
    drop procedure if exists p_hello_world;
    
    --创建存储过程
    create procedure p_hello_world()
    begin
        declare v_number int;
        declare v_varchar varchar(32);
        set v_number = 1;
        set v_varchar = 'hello world';
    
        select v_number;
        select v_varchar;
    end;
    
    -- 调用存储过程
    call p_hello_world();
    

选择语句

  • --删除存储过程
    drop procedure if exists p_hello_world;
    
    --创建存储过程
    create procedure p_hello_world(in v_id int)
    begin
        if (v_id > 0) then
            select '> 0';
        elseif (v_id = 0) then
            select '= 0';
        else
            select '< 0';
        end if;
    end;
    
    -- 调用存储过程
    call p_hello_world(-9);
    

循环语句

  • drop procedure if exists p_while_do;
    
    create procedure p_while_do()
    begin
        declare i int;
            set i = 1;
            while i <= 10 do
                select concat('index : ', i);
                set i = i + 1;
            end while;
    end;
    
    call p_while_do();
    
  • drop procedure if exists p_for_loop;
    
    create procedure p_for_loop()
    begin
        declare i int;
            set i = 1;
            loop_example : loop
                select concat('index -> ', i);
                set i = i + 1;
    
                if i > 10 then
                    leave loop_example;
                end if;
            end loop;
    end;
    
    call p_for_loop();
    

静态游标

  • --删除存储过程
    drop procedure if exists p_hello_world;
    
    --创建存储过程
    create procedure p_hello_world()
    begin
        declare empno integer;
        declare ename varchar(256);
        declare result varchar(4000) default '';
        
        declare cursor_emp cursor for select e.empno,e.ename from emp e;
        declare continue handler for SQLSTATE '02000' set empno = null; 
        open cursor_emp;
        fetch cursor_emp into empno, ename;
        while (empno is not null ) do
            set result = concat(result, 'empno:', empno, ',ename:', ename, ';');
            fetch cursor_emp into empno, ename;
        end while;
        close cursor_emp;
        select result;
    end
    
    -- 调用存储过程
    call p_hello_world();
    

触发器

简介

  • 触发器与数据表关系密切,主要用于保护表中的数据。
  • 特别是当有多个表具有一定的相互联系的时候,触发器能够让不同的表保持数据的一致性。
  • 在 MySQL 中,只有执行 INSERT、UPDATE 和 DELETE 操作时才能激活触发器

优缺点

  • 优点:
    • 触发器的执行是自动的,当对触发器相关表的数据做出相应的修改后立即执行。
    • 触发器可以实施比 FOREIGN KEY 约束、CHECK 约束更为复杂的检查和操作。
    • 触发器可以实现表数据的级联更改,在一定程度上保证了数据的完整性。
  • 缺点:
    • 使用触发器实现的业务逻辑在出现问题时很难进行定位,特别是涉及到多个触发器的情况下,会使后期维护变得困难。
    • 大量使用触发器容易导致代码结构被打乱,增加了程序的复杂性,
    • 如果需要变动的数据量较大时,触发器的执行效率会非常低。

类型

  • INSERT 触发器
    • 在 INSERT 语句执行之前或之后响应的触发器。
    • 在 INSERT 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问被插入的行。
    • 在 UPDATE 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问更新的值。
  • update触发器
    • 在 UPDATE 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问更新的值。
    • 在 UPDATE 触发器代码内,可引用一个名为 OLD(不区分大小写)的虚拟表来访问 UPDATE 语句执行前的值。
    • 在 BEFORE UPDATE 触发器中,NEW 中的值可能也被更新,即允许更改将要用于 UPDATE 语句中的值。
    • OLD 中的值全部是只读的,不能被更新。
  • Delete触发器
    • 在 DELETE 触发器代码内,可以引用一个名为 OLD(不区分大小写)的虚拟表来访问被删除的行。
    • OLD 中的值全部是只读的,不能被更新。
  • 对于事务性表,如果触发程序失败,以及由此导致的整个语句失败,那么该语句所执行的所有更改将回滚;
  • 对于非事务性表,则不能执行此类回滚,即使语句失败,失败之前所做的任何更改依然有效。

使用

  • 语法

    • CREATE TRIGGER <触发器名> < BEFORE | AFTER >
      <INSERT | UPDATE | DELETE >
      ON <表名> FOR EACH Row <触发器主体>
      
      1) 触发器名
      触发器的名称,触发器在当前数据库中必须具有唯一的名称。如果要在某个特定数据库中创建,名称前面应该加上数据库的名称。
      
      2) INSERT | UPDATE | DELETE
      触发事件,用于指定激活触发器的语句的种类。
      注意:三种触发器的执行时间如下。
      INSERT:将新行插入表时激活触发器。例如,INSERT的BEFORE触发器不仅能被INSERT 语句激活,也能被LOAD DATA 语句激活。
      DELETE: 从表中删除某一行数据时激活触发器,例如 DELETE 和 REPLACE 语句。
      UPDATE:更改表中某一行数据时激活触发器,例如 UPDATE 语句。
      
      3) BEFORE | AFTER
      BEFORE 和 AFTER,触发器被触发的时刻,表示触发器是在激活它的语句之前或之后触发。
      若希望验证新数据是否满足条件,则使用 BEFORE 选项;
      若希望在激活触发器的语句执行之后完成几个或更多的改变,则通常使用 AFTER 选项。
      
      4) 表名
      与触发器相关联的表名,此表必须是永久性表,不能将触发器与临时表或视图关联起来。
      在该表上触发事件发生时才会激活触发器。同一个表不能拥有两个具有相同触发时刻和事件的触发器。
      
      5) 触发器主体
      触发器动作主体,包含触发器激活时将要执行的 MySQL 语句。如果要执行多个语句,可使用 BEGINEND 复合语句结构。
      
      6) FOR EACH ROW
      一般是指行级触发,对于受触发事件影响的每一行都要激活触发器的动作。
      
    • 创建 BEFORE 触发器

      • -- 创建 ,每次将新增的薪资记录到一个局部变量中
        CREATE TRIGGER tr_salsum
        BEFORE INSERT ON emp
        FOR EACH ROW
        SET @sum=@sum+NEW.sal;
        
        -- 创建完成后 可以在设计表对应的触发器处看到
        
        -- 查看触发器的作用
        SET @sum=0;
        INSERT INTO `emp` VALUES ('9999', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', null, '10');
        select @sum;
        
    • 创建 AFTER 触发器

      • -- 首先创建一张相同的表
        create table dept_copy as select * from dept; 
        
        -- 向Dept插入数据的时候,也会向复制表中插入数据
        CREATE TRIGGER tr_chinaloc
        AFTER INSERT ON dept
        FOR EACH ROW
        INSERT INTO dept_copy
        VALUES (NEW.deptno,NEW.dname,concat('china-',NEW.loc));
        
        -- 测试 
        insert into dept values(88,'shop','shanghai');
        

查看

  • 在 MySQL 中,若需要查看数据库中已有的触发器,则可以使用 SHOW TRIGGERS 语句

  • -- 简单模式
    SHOW TRIGGERS;
    
    -- 指定触发器
    SELECT * FROM information_schema.triggers WHERE trigger_name= 'tr_chinaloc';
    

修改删除

  • 修改触发器可以通过删除原触发器,再以相同的名称创建新的触发器。

  • 删除一个表的同时,也会自动删除该表上的触发器。

  • 触发器不能更新或覆盖,为了修改一个触发器,必须先删除它,再重新创建。

  • -- DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名>
    DROP TRIGGER IF EXISTS tr_chinaloc;
    

事件

简介

  • 事件(event)是MySQL在相应的时刻调用的过程式数据库对象。一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是所谓的“事件调度器”。
  • 事件取代了原先只能由操作系统的计划任务来执行的工作
    • MySQL的事件调度器可以精确到每秒钟执行一个任务,
    • 操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每分钟执行一次。

开启事件

  • 查看是否开启

  • -- 是否开启
    show variables like '%event_scheduler%';
    
    -- 如果是关闭的(临时开启)
    set global event_scheduler = on;
    
    --如果是关闭的(长久开启)
    --修改my.ini中[mysqld]数据  C:\ProgramData\MySQL\MySQL Server 8.0
    event_scheduler=ON
    

创建事件

  • 一条create event语句创建一个事件。

  • 每个事件由两个主要部分组成

    • 第一部分是事件调度(eventschedule,表示事件何时启动以及按什么频率启动;
    • 第二部分是事件动作(event action),这是事件启动时执行的代码
  • 一个事件可以是活动(打开)的或停止(关闭)的

    • 活动意味着事件调度器检查事件动作是否必须调用
    • 停止意味着事件的声明存储在目录中,但调度器不会检查它是否应该调用。
  • 语法

    • CREATE
        [DEFINER = { user | CURRENT_USER }] 
        EVENT 
        [IF NOT EXISTS] 
        event_name 
        ON SCHEDULE schedule 
        [ON COMPLETION [NOT] PRESERVE] 
        [ENABLE | DISABLE | DISABLE ON SLAVE] 
        [COMMENT 'comment'] 
        DO event_body; 
         
      schedule: 
        AT timestamp [+ INTERVAL interval] ... 
        | 
        EVERY interval 
        [STARTS timestamp [+ INTERVAL interval] ...] 
        [ENDS timestamp [+ INTERVAL interval] ...] 
         
      interval: 
        quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | 
             WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | 
             DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
             
      #DEFINER:定义事件执行的时候检查权限的用户。
      #event_name:表示事件名称
      #SCHEDULE:表示触发点
      	AT timestamp一般用于只执行一次。
      	EVERY interval一般用于周期性执行,可以设定开始时间和结束时间。
      #ON COMPLETION PRESERVE:表示任务执行之后仍保留
      #ON COMPLETION NOT PRESERVE:表示任务执行完成后不保留
      #ENABLE|DISABLE:表示设置启用或者禁止这个事件。
      #COMMENT:添加注释
      
  • 案例

    • -- 立即启动事件
      create event event_now 
      on schedule 
      at now() 
      do insert into events_list values('event_now', now());
      
      -- 5秒钟后自动清空表
      CREATE EVENT IF NOT EXISTS event_truncate_dept_copy
      ON SCHEDULE
      AT CURRENT_TIMESTAMP + INTERVAL 5 SECOND
      DO TRUNCATE TABLE dept_copy;
      
      
      -- 每秒钟启动事件
      CREATE event event_SECOND 
      ON SCHEDULE 
      EVERY 1 SECOND
      DO INSERT INTO event_test VALUES(1);
      
      -- 每分钟启动事件
      create event event_minute 
      on schedule 
      every 1 minute 
      do insert into events_list values('event_now', now());
      
      --5天后开启每天定时3秒向表test2中插入数据,一个月后停止执行
      CREATE EVENT IF NOT EXISTS event_truncate_test3
      ON SCHEDULE 
      EVERY 3 SECOND
      STARTS CURRENT_TIMESTAMP + INTERVAL 5 day
      ENDS CURRENT_TIMESTAMP + INTERVAL  1 month
      ON COMPLETION PRESERVE
      DO INSERT INTO test2(department,time_v) VALUES('1',NOW());
      
      -- 每秒钟调用存储过程
      CREATE DEFINER=`root`@`localhost` EVENT `eventUpdateStatus` 
      ON SCHEDULE 
      EVERY 1 SECOND
      STARTS '2017-11-21 00:12:44'
      ON COMPLETION PRESERVE 
      ENABLE 
      DO call updateStatus()
      
  • 启用禁用

    • alter event event_name disable;
      alter event event_name enable;
      
  • 删除

    • drop event [if exists] event_name
      

JDBC

介绍

image-20201224173809404转存失败,建议直接上传图片文件
  • Java Database Connectivity 对应了 java和数据库的所有连接类
  • java.sql.*;
  • 全世界有多少数据库?
    • JDBC连接什么数据库? Oracle Mysql SqlServer?
    • JDBC最终目标就是能连接全世界所有的关系型数据库?
    • JDBC定义了一套操作数据库的接口!sun没有写任何的关于具体数据库的实现!
      • 而且会根据自己数据库版本更迭或者JDK版本更迭去更新JDBC的实现
    • 如果你的数据库想被java使用,你自己按照jdbc的接口写实现
  • 我们使用JDBC可以连接任意的关系型数据库
    • 我们只需要对应数据库的jar包就可以了

第一个JDBC程序

image-20201224173853816转存失败,建议直接上传图片文件
  • 添加jar包

    • mysql-connector-java-8.0.18.jar
  • 配置文件

    • //mysql5.x配置
      private static String driver="com.mysql.jdbc.Driver";
      private static String url="jdbc:mysql://localhost:3306/scott";
      private static final String user = "root";
      private static final String password = "root";
      
      
      //mysql8.x配置
      private static String driver="com.mysql.cj.jdbc.Driver";
      private static String url="jdbc:mysql://localhost:3306/scott?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT";
      private static final String user = "root";
      private static final String password = "123456";
      

JDBC的常见对象

  • DriverManager

    • 驱动管理器,用于加载驱动,
    • 使用这个驱动访问URL,然后通过用户名和密码获取连接
  • Connection

    • 和数据库的连接,可以传递SQL和结果
    • setAutoCommit
      • 设置事务是否自动提交
        • true:自动
        • false:非自动
      • 当connection正常关闭的时候,会提交事务
      • 当connection异常关闭的时候,会回滚事务
  • Statement

    • SQL语句的发送器,用于执行SQL语句
    • 执行方式
      • executeQuery -->查询操作 DQL
      • executeUpdate-->增删改操作 DML
      • execute-->数据库定义操作 DDL
  • PreparedStatement

    • 预处理清单对象,它的效率是要高于statement的,尤其是查询语句重复率较高的情况下
    • 使用占位符设置参数 ?代表了一个占位符,从1开始计数
  • ResultSet

    • 本次查询的结果集合
    • 里面包含了一个游标,默认在第一个数据之前
    • 调用next可以探测下一个位置是否存在数据,如果存在返回true,并向下移动
    • 我们会默认访问游标所指向的数据
    • 数据可以理解为一个map结果的数据,key为列名 value为本行的值
    • 最后根据数据类型 使用getXXX获取结果

案例:12306

image-20201224173700837转存失败,建议直接上传图片文件

火车票模块

车票信息

  • 出发点 目的地 日期

订单表

检票查询表

用户模块

账号表

安全校验

个人信息表

乘车人

地址信息

投诉建议