MySQL笔记

MySQL笔记


一、前期准备

  1. SQL语句分类
    • DQL - 数据查询语言 --> 查询语句,select 语句都是DQL

    • DML - 数据操作语言 --> insert、delete、update 等等对表数据进行增删改

    • DDL - 数据定义语言 --> create、 drop、 alter 等等对表结构的增删改

    • TCL - 事务控制语言 --> Transaction Commit - 提交事务 Rollback - 回滚事务

    • DCL - 数据控制语言 --> grant - 授权 revoke - 撤销权限

  2. MySQL卸载
    • 去安装目录找到my.ini文件

    • 复制文件中配置的路径:【 datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/" 】

    • 控制面板卸载MySQL

    • 去第二步里复制的路径中删除 C:/ProgramData下的MySQL文件夹

  3. 常见的cmd命令
    • 打开服务窗口 services.msc

    • 打开/关闭MySQL服务 net start/shut mysql

    • 登录MySQL mysql -uroot -p密码

    • 访问别人的MySQL mysql -h别人IP -uroot -p别人密码

    • 退出MySQL exit/quit


二、DDL -- 对数据库、表的操作

  1. 操作数据库
    • C(Create):创建
      • create database 数据库名;

      • create database if not exists 数据库名; -- 判断不存在再创建

      • create database 数据库名 character set 字符集名; -- 创建库并指定字符集

      • 练习: create database if not exists db0 character set utf8;

    • R(Retrieve):查询
      • show databases; -- 查询所有的数据库名

      • show create database 数据库名; -- 查看创建库的语句

    • U(Update):修改
      • alterdatabase 数据库名 character set 字符集名;
    • D(Delete):删除
      • drop database 数据库名;

      • drop database if exists 数据库名; -- 先判断是否存在

    • 使用数据库
      • 查询当前正使用的数据库

        • selsect database();
      • 使用数据库

        • use 数据库名;
  2. 操作表
    • C(Create):创建
      • 语法:create table 表名(列名1 类型1,

        列名2 类型2,

        列名3 类型3);

      • 数据库数据类型

        • int -- 整数类型

          • age int
        • double -- 小数类型

          • score double(3, 1); -- 最多三位,一位小数
        • date -- 日期 只包含年月日 yyyy- MM-dd

        • datetime -- 时间戳类型 包含年月日时分秒 yyyy- MM-dd HH:mm:ss

        • timestamp -- 包含年月日时分秒 yyyy- MM-dd HH:mm:ss

          • 如果不给这个字段赋值或赋值为null,则默认值为系统当前时间
        • varchar -- 字符串

          • name varchar(20);

          • 张三 8个字符 zhangsan 两个字符

      • 复制表 -- create table 表名 like 源表名

      • 练习:

      create table t_student(
      id int,
      name varchar(30),
      age int,
      score double(4,1),
      birthday date,
      insert_time timestamp);
      
    • R(Retrieve):查询
  • show tables; -- 查询当前数据库的所有表

  • desc 表名; -- 查询表结构

    • U(Update):修改
      • 修改表名

        • alter table 表名 rename to 新表名
      • 修改表字符集

        • alter table 表名 character set 字符集名;
      • 添加一列

        • alter table 表名 add 列名 类型;
      • 修改列名称、类型

        • alter table 表名 change 列名 新列名 新类型;

        • alter table 表名 modify 列名 新类型;

    • 删除列

  • alter table 表名 drop 列名;

    • D(Delete):删除
      • drop table if exists 表名;

三、DML -- 增删改表中数据

  1. 添加数据
    • 语法:
      • insert into 表名(列名1, 列名2, 列名3...) values(数据1, 数据2, 数据3...);
    • 注意!!
        1. 前后括号的 列名和值(类型)要一一对应

        2. 如果表名后不定义列名,则默认给所有列添加值 (也要对应上所有坑,不然报错)

          • insert into stu values(2, 'Jones', 18, 90.7, null,null);
        3. 除了数值类型,其他的类型都需要是哟个引号括起来【单双引号都可】

  2. 删除数据
    • 语法:
      • delete from 表名 [where 条件 ];
    • 注意!!
      • 如果不写条件则会删除表中所有记录

      • 如果要删除所有记录,有两种方式:

        • delete from 表名; -- 有多少条记录都会一条一条删除掉

        • truncate table 表名; -- 先删除整张表【包括其数据】,然后创建一张一模一样的空表,效率高

  3. 修改数据
    • 语法:

      • update 表名 set 列名1 = 值1, 列名2 = 值2...[where 条件]
    • 注意!!

      • 如果不加任何条件,则会将表中所有记录全部修改

四、DQL -- 查询语句

  1. 查询表中记录
    1. 语法:
       select 
            字段列表
       from 
            表名列表
       where 
            条件列表
       group by  
            分组字段
       having   
            分组之后补充的条件
       order by 
            排序
       limit 
           分页查询
      
    2. 基础查询

      • 多个字段的查询

        • select name, age from stu;

        • 有null参与的任何运算结果为null 如下:

          • 解决方案:在可能出现问题的计算的地方添加ifnull(表达式1, 表达式2)即可

            • 表达式1 -- 哪个字段需要判断是否为null

            • 表达式2 -- 如果该字段值为null,替换为表达式2值

          • SELECT s.name, s.math, s.english, (ifnull(s.math, 0) + ifnull(s.english, 0)) totalScore FROM stu s ;

      • 去除重复

        • select distinct address from stu; -- 地址重复去除
      • 起别名

        • SELECT s.name AS 姓名,(IFNULL(s.math, 0) + IFNULL(s.english, 0)) AS 总分 FROM stu s ; -- as 看省略

    3. 条件查询
      1. where子句后跟条件

      2. 运算符

        • <、>、<=、>=、=、<>

          • 查询年龄大于20岁的

            select * from stu where age > 20;

        • beteen...and

          查询年龄位于20-30岁的
           SELECT * FROM stu WHERE age <= 30 && age >= 20;
           SELECT * FROM stu WHERE age BETWEEN 20 AND 30;  #推荐写法
          
        • like

          • 模糊查询

          • 占位符

            • _ 表示单个任意字符

            • % 表示多个任意字符

          • 举例:

              # 查询姓马的记录  第一个字是“马”,其余任意多字无所谓
          SELECT s.name, s.math, s.english FROM stu s WHERE s.name LIKE '马%';
             # 查询姓名中第二个字是'化'的人
          SELECT * from stu where name like '_化%';  # 第一个任意
             # 查询姓名有三个字的人
          SELECT * FROM stu WHERE NAME LIKE '___';  # 三个下划线
             # 查询姓名中包含“马”和“德”的人
          SELECT * FROM stu WHERE NAME LIKE "%德%" OR "%马%";
          
          • is null
            #查询英语成绩为null的列 与不为null的列
          SELECT s.name FROM stu s WHERE s.english IS NULL;
          SELECT s.name FROM stu s WHERE s.english IS NOT NULL;
          
          • and 或者 &&

          • or 或者 ||

            # 查询年龄为19 22 25 的
          SELECT * FROM stu WHERE age = 19 or age = 22 or age = 25;
          SELECT * FROM stu WHERE age in(18, 22, 25);  #推荐写法
          
          • not 或者 !
    4. 排序查询
      1. 语法:order by 子句

        • order by 排序字段1 排序方式1, 排序字段2 排序方式2...
      2. 排序方式:

        • asc:升序【默认】

        • desc :降序

      3. 注意!!如果有多个排序条件,则当前边的条件值一样时,才会执行第二判断条件

      4. 练习:

            # 按照数学成绩排名,如果数学一样,则按照英语成绩排名
         SELECT * FROM stu ORDER BY math ASC, english ASC; 
             # 先按照前面的升序,如果前面的一样则再按照后面的升序
        
    5. 聚合函数 -- 将一列数据作为一个整体,进行纵向的计算
      1. count -- 计算个数

        • 一般选择主键
      2. max -- 计算最大值

      3. min -- 计算最小值

      4. sum -- 计算和

      5. avg -- 计算平均数

           # 看下英语成绩平均值
          SELECT AVG(IFNULL(english, 0)) FROM stu;</pre>
      
      1. 注意!!聚合函数计算,是排除null值的

        • 解决方案一:选择不包含null的列进行计算

        • 解决方案二:使用ifnull函数 SELECT COUNT(IFNULL(english, 0)) FROM stu;

    6. 分组查询 -- 统计某一类具有相同特征的数据,把他们看做一个整体
      1. 语法:group by分组字段

             # 按照性别分组,看下男女同学的平均分
          SELECT sex 性别, AVG(IFNULL(math, 0))  数学平均分, AVG(IFNULL(english, 0)) 英语平均分 FROM stu GROUP BY sex;
             # 按照性别分组,看下男女同学的平均分 分数低于70的同学不参与分组
          SELECT sex, AVG(IFNULL(math, 0)), AVG(IFNULL(english, 0)), COUNT(id) FROM stu WHERE IFNULL(math, 0) > 70 GROUP BY sex;
        
             # 按照性别分组,看下男女同学的平均分 分数低于70的同学不参与分组,
             # 且分组后组内个数小于2的不要了
          SELECT sex, AVG(IFNULL(math, 0)), AVG(IFNULL(english, 0)), COUNT(id) FROM stu WHERE IFNULL(math, 0) > 70 GROUP BY sex HAVING COUNT(id) > 2;
        
      2. 注意!!

        • 分组之后查询的字段只能是分组字段或者聚合函数了,不能有与个人有关的字段

        • wherehaving的区别

          • where在分组之前【order by】进行限定,而having在分组之后进行限定

          • where后不可以跟聚合函数,而having可以

    7. 分页查询
      1. 语法:limit index, n index -- 开始的索引; n -- 每页查询的条数

      2. 公式:【当前页开始索引 = (当前页数 - 1) * 每页记录条数

            # 每页显示三条,第一页
          SELECT * FROM stu LIMIT 0, 3;
            # 第二页
          SELECT * FROM stu LIMIT 3, 3;
            #  第三页
          SELECT * FROM stu LIMIT 6, 3; 
            # 每页开始索引    (当前页数 - 1) * 每页显示条数 = 每页开始索引
        
      3. 分页操作是一个方言 【在MySQL中分页是limit,其他数据库有各自额关键字】

  2. 约束
    1. 概念:对表中数据进行限定,保证数据的正确性、有效性与完整性

    2. 约束分类:

      • 主键约束:primary key

      • 非空约束:not null

      • 唯一约束:unique

      • 外键约束:foreign key

    3. 主键 -- 该字段值非空且唯一

      • 注意!!

          1. 一张表只能有一个字段为主键

          2. 主键就是表中记录的唯一标识

      • 创建表时添加主键

          # 创建一个新表,id是主键
         create table stu1(
          id int primary key,
          name varchar(30) not null  #  name字段非空
         ); # 一个表只能有一个主键
        
      • 删除主键

        alter table stu1 drop primary key;  #  一个表只有一个主键
        
      • 创建表之后添加主键

          # 给 id 字段添加约束主键
         alter table stu1 modify id int primary key;
        
        • 添加前删除所有重复字段
    4. 非空 -- 值不能为null

      • 创建表时添加非空约束

            # 创建一个新表,name字段非空
         create table stu1(
          id int,
          name varchar(30) not null -- name非空
         );
        
      • 删除已经创建的表的非空约束

           # 给name字段添加约束非空
         alter table stu1 modify name varchar(30) not null;
        
    5. 唯一 -- 值不能重复

      • 创建表时添加

           # 创建一个新表,phoneName唯一
         CREATE TABLE stu1(
          id INT,
          phoneName VARCHAR(20) UNIQUE # phoneName唯一
         );
        
      • 创建表之后添加

           #  给 phoneName 字段添加约束唯一
         alter table stu1 modify phoneName varchar(20) unique;
        
      • 删除表字段的的唯一约束

            alter table stu1 drop index phoneName;  # 删除表phoneName字段唯一约束
        
      • 注意!!

        • MySQL中unique限定的值可以有多个null

        • 删除唯一约束的语法特殊

        • 给已经创建的表的某个字段添加唯一约束时,需要删除掉该字段所有的重复的值

    6. 自动增长

      • 概念:如果某一字段是数值类型,使用auto_increment可以实现其自增【一般配合主键id一起使用】

      • 创建表时添加自增约束

            # 创建一个新表,id是主键,且自增
         create table stu1(
          id int primary key auto_increment,
          name varchar(30) not null -- name字段非空
         );
        
        • 注意!!自增的数据只跟上一条记录有关,如id自增到6,插入数据时,指定了id为20 则下一次自增从21开始
      • 删除自增约束

            # 删除自增约束
         alter table stu1 modify id int; # id的主键约束不会被删除掉
        
      • 添加自增约束

             # 给 id 字段添加约束自增
         alter table stu1 modify id int auto_increment;
        
    7. 外键 -- 添加外键前,外键表删除数据不会做检查【比如小李还在A部门,删除A部门不会做检查】

      1. 在创建表时。可以添加外键
          create table 表名(
          ...
          外键列,
          constraint 外键名 foreign key (外键列名) references 主表名(主表列名)
         );
        
      2. 删除外键
            # 删除外键
         alter table 本表名 drop foreign key 外键名称;
        
      3. 创建表之后,添加外键
         alter table 本表名 add constraint 外键名 foreign key (要关联的本表列名) references 外键表名(要关联的外键表列名);
           #  如下
          alter table emp add constraint emp_edp_fk foreign key (dep_id) references dep(id);
        
      4. 添加外键,并设置级联更新[ -- 【更改/删除部门的id时,在员工表里自动更改了对应员工的部门号】用的时候谨慎
            # 添加外键,并设置级联更新与级联删除
         ALTER TABLE emp ADD CONSTRAINT emp_edp_fk FOREIGN KEY
         (dep_id) REFERENCES dep(id) ON UPDATE CASCADE ON DELETE CASCADE;
        

五、数据库的设计

  1. 多表之间的关系
    1. 分类

      • 一对一(了解)

        • 如:人与身份证

        • 一个人只能有一个身份证,一个身份证只能对应一个人

      • 一对多(多对一)

        • 如:部门与员工

        • 一个部门可以有多个员工,一个员工只能对应一个部门

      • 多对多

        • 如:学生与课程

        • 一个学生可以选择多个课程,一个课程也可以被很多学生选择

    2. 如何实现
      • 一对多(多对一)

        • 如:部门与员工

        • MySQL实现:

          在多的一方【员工表】建立外键,指向一的一方【部门表】的主键

          总结 一对多两张表,多的一方加外键

      • 多对多

        • 如:学生与课程

        • MySQL实现:

          多对多关系实现需要借助第三张表,此第三话张表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键【选课表】

          总结 多对多,三张表、关系表俩外键

      • 一对一【了解】

        • 一对一关系实现,在任意一方添加唯一外键指向另一方主键【直接放一张表吧。。。。】
  2. 范式
    1. 概念:设计数据库时,遵循不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小

    2. 分类:(目前关系型数据库有六种范式)

      • 第一范式(1NF): 任何一张表应该有主键,且每一个字段原子性不可再分

        • 如下图的系列还分两列,且存在问题【比如删除了张无忌会一起删除了高等数学课程】

      • 第二范式(2NF): 建立在1NF之上 另外要求所有非主键字段完全依赖主键,不能产生部分依赖 【消除非主字段对主键的部分函数依赖】

        • 几个概念

          • 函数依赖:A --> B ,如果通过A列的值可以唯一确定列B的值,则称B依赖于A

            • 如 学号 --> 姓名 姓名依赖于学号

            • (学号,课程) --> 分数 则分数依赖于属性组

          • 完全函数依赖: A --> B 如果A是一个属性组,则B值的确认依赖于A中每一个属性

            • 如:(学号,课程) -- > 分数 分数的确定单由一个学号无法确定,单由课程也无法确定,一个确定的学号+一个确定的课程确定唯一一个分数
          • 部分函数依赖: A --> B 如果A是一个属性组,则B值的确认依只需要依赖于A中某一部分属性

            • 如:(学号,系名) --> 姓名。我们发现前面属性组里,通过一个学号可以确定一个姓名,不需要系名,用这个属性组局多余
          • 传递依赖:A --> B, B -- > C,如果通过A属性(组)可以唯一确定B属性的值,再通过B属性(组)的值可以唯一确定C属性(组)的值,则C传递依赖于A

        • 如:

          • 图:

          • 学号与课程名可以作为主码【由(学号, 课程)可以唯一确定一个其他的唯一的值】,而系名与系主任可由学号直接确定,产生了部分依赖

          • 解决方案:拆分出选课表【学号、课程、分数】作为主码,与学生表【还存在传递依赖问题】

      • 第三范式(3NF): 建立在2NF基础上,所有外键字段直接依赖主键,不可产生传递依赖

        • 如:

          • 图:

          • 系名依赖于学号,系主任依赖于系名 则系主任传递依赖于学号 解决:拆分表,把系名与系主任另开为系表

  3. 数据库的备份与还原
    1. 命令行形式

      • 备份:mysqldump -u用户名 -p密码 要备份的数据库 > 保存的路径

        mysqldump -uroot -padmin db1 > D:\JavaSETestDirectory01\MySQLBackup\db1.sql

      • 还原:

          1. 登录数据库

          2. 创建数据库【还原的数据装在此数据库】

            create database backupdb;

          3. 使用数据库【进入这个数据库,把数据还原进来】

            use backupdb;

          4. 执行文件。source 文件路径

            source D:\JavaSETestDirectory01\MySQLBackup\ddd.sql

    2. 图形化工具


六、多表查询

  1. 查询语法:
    select 列名列表 from 表名列表 where ...

    • 笛卡尔积:两个集合,其所有情况为两个集合列的乘积

    • 消除笛卡尔积:下面三种方式

  2. 多表查询分类:

    1. 内连接:

      1. 隐式内连接:使用where条件消除无用数据
      SELECT 
           e.name,  # 员工表姓名
           e.gender,   # 员工表性别
           d.name  # 部门表名
      FROM
           emp e, dep d
      WHERE
           e.dep_id = d.id;  # 当员工的部门id与部门的id相等时才返回结果
      
      1. 显示内连接:显示地指定连接方式
      • 语法:
        select 字段列表 from 表1 inner join 表2 on 条件
        
           # 显示连接  查询所有的员工信息与对应的部门信息
        SELECT  * FROM emp e INNER JOIN dep d ON e.dep_id = d.id;    #  inner可省略
        
      • 可以看出内连接,查询的是两张表的交集
      1. 内连接注意事项:

        1. 从哪些表中查询数据

        2. 条件是什么

        3. 查询哪些字段

    2. 外连接

      1. 左外连接

        • 语法:
         select 字段列表 from 表1 left outer join 表2 on 条件  # outer可省略
        
        # 查询所有的员工信息,如果员工有部门,则查询部门名称。没有则不显示部门名
         SELECT * FROM emp e LEFT OUTER JOIN dep d ON e.`dep_id` = d.`id`;
        
        • 可以看出--左外连接是查询的左边的表另外与右边表的交集
          image
      2. 右外连接

        • 语法:
         select 字段列表 from 表1 right outer join 表2 on 条件  # outer可省略
        
        • 右外连接查询的就是右边的表及其交集
    3. 子查询

      1. 概念:查询中嵌套查询,称嵌套查询为子查询

      2. 案例: -- 查询工资最高的员工信息

        # 先查询最高工资是多少
         select * from emp where salary = 9000;   # 带着最高工资查询信息
        # 查询工资最高的员工信息,使用子查询
         SELECT * FROM emp WHERE salary = (SELECT MAX(salary) FROM emp);
        
      3. 子查询不同情况

        • 子查询是单行单列的

          • 子查询可以作为条件,使用运算符取判断,运算符【>, <, >=, <=, =】
          # 查询工资小于平均工资的员工信息
         SELECT * from emp where salary < (SELECT avg(salary) e from emp);
        
        • 子查询是多行单列的

          • 子查询作为条件,使用运算符in作为判断
        # 查询在开发部或者市场部工作的员工
        SELECT * FROM emp WHERE dep_id IN (( SELECT id FROM dep WHERE NAME = "开发部" ), ( SELECT id FROM dep WHERE NAME = "市场部" ));
        
image-20200302190004915

* 子查询是多行多列的

         # 子查询可以作为一张临时表参与查询
         # 查询员工入职日期是 2011-11-11 日之后的员工信息和部门信息
         # 使用普通的内连接
       SELECT * from emp e, dep d where e.dep_id = d.id and e.join_date > "2011-11-11";
         # 使用子查询  多行多列
      SELECT * from (select * from emp where emp.join_date > "2011-11-11") t, dep d  where t.dep_id = d.id;
  1. 多表查询练习:

    1. 查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述

    2. 查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置

    3. 查询员工姓名,工资,工资等级

    4. 查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级

    5. 查询出部门编号、部门名称、部门位置、部门人数

    6. 查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询

    7. 答案:

     # 1.  查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
    select e.id 员工编号, e.ename 员工姓名, e.salary 工资, j.jname 职务名称, j.de 职    务描述 from emp e, job j where e.job_id = j.id;
    
    # 2.  查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位    置
    select e.id, e.ename, e.salary, j.jname, j.de, d.dname, d.loc from emp e, dep d,     job j where e.dep_id = d.id and e.job_id = j.id;
    
    # 3.  查询员工姓名,工资,工资等级
    SELECT e.ename, e.salary, s.grade from emp e, salarygrade s where e.salary     between s.losalary and s.hissalary;
    
    # 4.  查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等    级
    select e.ename, e.salary, j.jname, j.de, d.dname, d.loc, s.grade from emp e, dep     d, job j, salarygrade s where e.dep_id = d.id and e.job_id = j.id and e.salary     BETWEEN s.losalary and s.hissalary;
    
    # 5.  查询出部门编号、部门名称、部门位置、部门人数
            /*
                分析:
        ·               1. 使用分组查询,对 emp.dep_id  字段进行分组,查询部    门的id与其对应数量 COUNT(emp.id) 作为临时表 t
                        2. 把 1 中的表拿出来 子查询与 dep 表连接查询部门信息
                    条件:当临时表的id与部门表id相同时
    */
    SELECT
        dep.id 部门编号,
        dep.dname 部门,
        dep.loc 部门位置,
        t.tcount 部门人数
    FROM
        dep,
        (
            SELECT
            emp.dep_id tid,
            COUNT(id) tcount
        FROM
            emp
        GROUP BY
            dep_id
        ) t
    WHERE
        t.tid = dep.id
    # 6.  查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
    select t1.t1ename 员工姓名, emp.ename 上级领导 from (select ename         t1ename,mgr t1mgr from emp) t1 LEFT OUTER JOIN emp on emp.id = t1.t1mgr; 
        -- 更简单的,起别名把员工表看做另一张领导表
    SELECT 
            e.ename,
        e.mgr,
        m.id,
        m.ename
    FROM
        emp e LEFT OUTER JOIN emp m 
    ON
        e.mgr = m.id;
    

七、事务

  1. 事务介绍
    1. 概念一个包含多个步骤的业务操作,被事务管理,那么这些事务要么同时成功,要么同时失败【开启事务后中间某一步出现问题就回滚到所有步骤之前,没有任何异常则提交事务】

    2. 操作

      1. 开启事务:start transaction

      2. 回滚:rollback

      3. 提交:commit 【如果手动开启了事务但没有手动提交,事务会回滚】

    3. MySQL中数据库事务默认自动提交

      • 一条DML(增删改)语句会自动提交一次事务

      • 事务提交的两种方式:

        • 自动提交 -- MySQL是自动提交的【Oracle数据库时默认手动提交的(需要写commit)】

        • 手动提交 -- 需要手动start开启事务,然后手动commit提交

      • 修改事务的提交方式

        • 查看事务默认提交方式:select @@autocommit; -- 1为自动提交 0 为手动提交

          image-20200303135300042.png
        • 修改默认提交方式:SET @@autocommit = 0

  2. 事务的四大特征
    1. 原子性:事务是不可分割的最小操作单位,要么同时成功,要么同时失败

    2. 持久性:事务提交或回滚后,数据会持久化保存【关机,重启应用都已经保存】

    3. 隔离性:多个事务之间相互独立【期望互不影响】

    4. 一致性:事务操作前后,事务的总量不变【转钱前A100,B100。转钱后A20,B180】

  3. 事务的隔离级别(了解)
    1. 概念:多个事务之间是隔离的、独立的。但是如果多个事务曹组同一批数据,则会引发一些问题,设置不同的隔离级别可以解决这些问题

    2. 存在的问题:

      • 脏读:一个事务,读取到另一个事务汇总没有提交的数据

      • (虚 读)不可重复读:在同一个事务中,两次读取到的数据不一样

      • 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改

    3. 隔离级别:

      • read uncommitted:读未提交

        • 产生的问题:脏读、不可重复读、幻读

          • 左边事务更改信息还未提交或者回滚,右边读取到更新的信息【比如AB开启事务,A给B转账500,但未提交,B可以看到自己的账户多了500,但是A此时回滚可以把这500不转过去】
      • read committed :读已提交【Oracle默认】

        • 产生的问题:不可重复读、幻读

          • 左边事务提交更新信息,右边事务在提交之前可以看到更新的信息,而不是保持不变
      • repeatable read:可重复读【MySQL默认】

        • 产生的问题:幻读【左边事务提交更新的信息,但右边事务未提交之前,右边事务读到的数据是不会改变的(实际上已经改变了)。只有在右边事务提交之后才会看到更新的数据信息】
      • serializable:串行化

        • 可以解决所有的问题

        • 一个锁表的操作,一个事务在开启并操作【增删改查】时,其他任何事物不得操作【比如查询时会卡住不动】,只有当前操作事务提交/回滚,别的事务才能操作【效率低】

        注意!!隔离级别从小到大安全性愈高,但是效率愈低

    4. MySQL查询隔离级别

      • 查询:select @@tx_isolation

      • 修改:set global transaction isolation level 级别字符串 【级别字符串是上述的read uncommitted等】


八、DCL -- 控制权限与管理用户

  1. DBA :数据库管理员 -- 管理用户,授权

  2. 管理用户

    1. 添加用户:

       # 创建用户【使用DCL语句】
       # create user "用户名"@"主机名" IDENTIFIED by "密码";
       create user "aaa"@"localhost" IDENTIFIED by "123";  -- 这样就可以使用  mysql -uaaa -p123访问这个数据库 
      
    2. 删除用户:

       # 删除用户
       # drop user "用户名"@"主机名":
       drop user "aaa"@"localhost";
      
    3. 修改用户密码:

       #可行的
       # set password for "用户名"@"主机名" = password("新密码");
       set password for "aaa"@"localhost" = password("345");
      
      1.          ```
        
         # update user set PASSWORD = PASSWORD("新密码") where user = "用户名";
         update user set PASSWORD = PASSWORD("123") where user = "aaa";  #### 实测不行 =.=
        
      2. 如果忘记了自己的登录密码... =.=

        1. 停止MySQL服务 cmd --> net stop mysql 需要管理员权限

        2. 使用无验证启动MySQL服务:mysqld --skip-grant- tables

        3. 再新打开一个cmd窗口 输入mysql 回车登录

        4. 使用 mysql 表,改密码

         use mysql;
         set password for "root"@"localhost" = password("新密码");
             # 或者下面这条命令
         update user set password = password('新密码') where user = 'root';
        
        1. 关闭两个窗口

        2. 打开任务管理器,手动结束mysqld.exe进程

        3. 启动mysql服务。使用新密码登录

    4. 查询用户:

      1. 切换到mysql数据库,用户表是mysql下的user

         use mysql;
         show tables;
         select * from user;  #可以发现有两个用户,上面这个是本机登录,第二个是%通配符 任意的【远程登录】
        

        image-20200303164817539
        有两个用户记录,上面的是本地主机,下面的是 % 通配符,表示可以在任意主机使用用户登录数据库

  3. 权限管理(权限授予、添加)

    1. 查询权限

       # 查询权限   普通创建的用户只有登录的权限
       #  show grants for '用户名'@'主机名';
       SHOW GRANTS FOR 'aaa'@'localhost';
      
    2. 授予权限

       # 授予权限  给谁授予哪个数据库的哪个表什么权限
       # grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
       GRANT SELECT, UPDATE, DELETE ON db3.emp TO 'aaa'@'localhost';
      

      2.1 授予全部权限

       # 授予所有权限,在所有数据库的所有的表上【谨慎使用】
       GRANT SELECT, UPDATE, DELETE ON db3.emp TO 'aaa'@'localhost';            
      
    3. 撤销权限

       # 撤销权限  从谁撤销哪个数据库的哪个表什么权限
       # revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
       revoke select on db3.emp from 'aaa'@'localhost'; 
      
      1. 撤销所有权限
       revoke  all on *.* from 'aaa'@'localhost';
      
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • DDL1.创建库、创建表使用关键字create2.删除库、删除表使用关键字drop3.修改库、修改表使用关键字al...
    王_凯阅读 347评论 0 0
  • ORACLE自学教程 --create tabletestone ( id number, --序号usernam...
    落叶寂聊阅读 1,066评论 0 0
  • 1. 了解SQL 1.1 数据库基础 ​ 学习到目前这个阶段,我们就需要以某种方式与数据库打交道。在深入学习MyS...
    锋享前端阅读 1,038评论 0 1
  • 1、MySQL启动和关闭(安装及配置请参照百度经验,这里不再记录。MySQL默认端口号:3306;默认数据类型格式...
    强壮de西兰花阅读 633评论 0 1
  • 典型子查询 一个查询的输出是另一个查询的输入,也称为嵌套子查询 5个关键点:1、在查询时基于未知时应考虑使用子查询...
    gg大宇阅读 343评论 0 4