• Java EE入门(五)——MySQL基础 (多表关系、范式、多表查询、事务、DCL)


    Java EE入门(五)——MySQL基础 (多表关系、范式、多表查询、事务、DCL)
      iwehdio的博客园:https://www.cnblogs.com/iwehdio/

    导图

    1、多表关系

    • 多表之间的关系:

      1. 一对一的关系。
      2. 一对多 或 多对一 的关系。
      3. 多对多的关系。
    • 一对多关系实现:在多的一方建立外键列,指向一的一方的主键。

    • 多对多关系实现:需要借助第三张中间表,中间表中至少包含两个字段,作为外键分别指向两张表的主键。这两个字段构成了联合主键。

    • 一对一关系实现:在任意一方添加外键列,指向另一方的主键。而且需要在外键列添加唯一约束。

    • 分析示例:用户收藏旅游线路。

      1. 三个实体:旅游线路分类、旅游线路、用户。

      2. 旅游线路分类和旅游线路是 一对多 的关系。

      3. 用户和收藏的旅游线路是 多对多 的关系。

      4. 实现:

        CREATE TABLE category(
        	cid INT PRIMARY KEY AUTO_INCREMENT,
        	cname VARCHAR(100) NOT NULL UNIQUE
        );
        
        CREATE TABLE route(
        	rid INT PRIMARY KEY AUTO_INCREMENT,
        	rname VARCHAR(100) NOT NULL UNIQUE,
        	CONSTRAINT r_c FOREIGN KEY (rid) REFERENCES category(cid)
        );
        
        CREATE TABLE users(
        	uid INT PRIMARY KEY AUTO_INCREMENT,
        	uname VARCHAR(100)
        );
        
        CREATE TABLE favorite(
        	rid INT,
        	uid INT,
        	PRIMARY KEY(rid,uid),	# 添加联合主键
        	CONSTRAINT f_r FOREIGN KEY (rid) REFERENCES route(rid),
        	CONSTRAINT f_u FOREIGN KEY (uid) REFERENCES users(uid)
        );
        

    2、范式

    • 数据库设计的范式:设计数据库时,所需要遵循的规范。

      • 目前关系数据库有六种范式,各个范式呈递次规范。即要遵循某个的范式,必须先遵循前边的范式。主要的是前三种范式。

      • 第一范式:每一列都是不可分割的原子数据项。

        可能存在一些问题:

        • 存在严重的数据冗余、重复。
        • 数据添加可能存在问题。
        • 数据删除可能会将将相关的数据都受到影响。
      • 第二范式:在第一范式的基础上,非码属性必须完全依赖于码(在第一范式的基础上消除非主属性对主码的部分函数依赖)。

        • 函数依赖:如果通过A属性(属性组,即多个属性的组合)的值,可以唯一确定B属性的值,则称B依赖于A。
        • 完全函数依赖:如果A是一个属性组,则B属性值的确定需要依赖于A属性组中的所有属性值。
        • 部分函数依赖:如果A是一个属性组,则B属性值的确定只需要依赖于A属性组中的部分属性值。
        • 传递函数依赖:如果B依赖于A,C依赖于B,则称C传递函数依赖于A。
        • 码:如果在一张表中,一个属性或属性组,被其他所有属性或属性组依赖,则称其为这张表的码。
          • 主属性:码属性组中的所有属性。
          • 非主属性:除了码属性组中的属性。

        可能存在一些问题:

        • 解决了数据的冗余、重复问题。
        • 没有解决数据添加和删除的问题。
      • 第三范式:在第二范式的基础上,任何非主属性不依赖于其他非主属性(在第二范式的基础上消除传递依赖)。

        • 解决了数据添加和删除的问题。
    • 使用三个范式的示例:学生成绩表。

      • 原始表分为,列:学号、姓名、系、课程名称和分数。其中系列下分为系名和系主任。
      • 应用第一范式:将系列分割为列系名和系主任。
      • 应用第二范式:
        • 原表中,主属性组是 学号和课程名称,分数同时依赖于主属性组,但姓名、系名和系主任只部分依赖于主属性组中的学号。
        • 将原表分为选课表和学生表。选课表包括列:学号、课程名称和分数。主属性组是学号和课程名称,分数完全依赖于主属性组。学生表包括列:学号、姓名、系名和系主任。主属性是学号,其他非主属性完全依赖于主属性。
      • 应用第三范式:
        • 在学生表中,系主任对学号是传递依赖。
        • 将原学生表分为学生表和系表。系表包括列:系名和系主任。系名为主属性,系主任完全依赖于系名。
    • 数据库的备份与还原:

      • 命令行备份:mysqldump -u用户名 -p密码 数据库名 > 保存的路径
      • 命令行还原:
        1. 登录数据库。
        2. 创建数据库。
        3. 使用数据库。
        4. 读入备份文件:source 备份路径

    3、多表查询

    • 从多张表中查询数据:select * from 表1,表2。得到的是表1和表2中内容的笛卡尔积(所有排列组合)。完成多表查询需要消除笛卡尔积中无用的数据。

    • 多表查询的分类:

      1. 内连接查询。
      2. 外连接查询。
      3. 子查询。
    • 内连接查询:

      • 隐式内连接:使用 where 条件,查询满足条件的数据。
        • select 列名列表 from 表1,表2 where 条件字段
        • 使用 表名.列名 的方式,获取不同表中的列。表名也可以用别名替代。
      • 显式内连接:
        • select 列名列表 from 表名1 inner join 表2 on 条件字段
        • inner 关键字可以省略。
      • 内连接查询步骤:
        1. 确定所要查询的表。
        2. 确定查询的条件。
        3. 查询哪些字段(列)。
      • 内连接查询的是两个表的交集部分,
    • 外连接查询:

      • 左外连接:
        • select 列名列表 from 表1 left outer join 表2 on 条件字段
        • outer 关键字可省略。
        • 左外连接查询的是左表(表1)的所有数据以及其(与表2)交集部分。
      • 右外连接:
        • select 列名列表 from 表1 right outer join 表2 on 条件字段
        • 右外连接查询的是右表(表2)的所有数据以及其(与表1)交集部分。
    • 子查询:

      • 查询中嵌套查询,称嵌套查询为子查询。
      • 子查询语句需要被括号()括起来。

      子查询的不同情况:

      • 子查询的结果是单行单列的:
        • 子查询的结果可以作为条件,使用单值判断运算符 >, <, = 做判断。
      • 子查询的结果是多行单列的:
        • 子查询的结果可以作为条件,使用关系判断运算符 in 做判断。
      • 子查询的结果是多行多列的:
        • 子查询到的结果可以作为一张虚拟表,作为被查询的对象。

    4、事务

    • 事务:如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。

    • 事务中的操作:

      1. 开启事务:start transaction。在事务的所有步骤开始前开启。
      2. 回滚:rollback。如果有一个步骤出问题则回滚,将数据库还原到开启事务时的状态。
      3. 提交事务:commit。如果没有出现问题,则正常运行,提交事务。如果没有提交事务,数据只会被暂时更改,关闭进程后会默认回滚。
    • MySQL 数据库中事务默认自动提交,一条 DML(增删改) 语句会提交一次事务。如果是手动开启事务的,也必须手动提交。

    • 查看默认提交方式:select @@autocommit,1代表自动提交,0代表手动提交。set @@autocommit = 0,可更改为默认手动提交。

    • 事务的四大特征:

      • 原子性:不可分割的的最小操作单位,要么同时成功,要么同时失败。
      • 持久性:事务一旦提交或者回滚,数据库的会持久化保存数据。
      • 隔离性:多个事务之间,希望是相互独立的。
      • 一致性:事务操作前后,数据总量不变。
    • 事务的隔离级别:

      • 多个事务之间是隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的事务隔离级别可以解决这些问题。

      • 会存在那些问题:

        1. 脏读:一个事务,读取到了另一个事务中没有提交的数据。
        2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
        3. 幻读:一个事务操作(DML)数据表中的所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
      • 隔离级别:

        1. read uncommitted:读未提交。可能会产生:脏读、不可重复读、幻读。
        2. read committed:读已提交。可能会产生:不可重复读、幻读。(Oracle默认)
        3. repeatable read:可重复读。可能会产生:幻读。(MySQL默认)
        4. serializable:串行化,相当于对表加锁,同一时间只能有一个事务对这张表进行操作或查询。不会出现任何问题。
        • 隔离级别从小到大安全性越来越高,但是效率越来越低。
      • 数据库查询隔离级别:select @@tx_isolation

      • 数据库设置隔离级别:set global transaction isolation level 隔离级别

    5、DCL

    • 管理用户:

      • 查询用户:切换到 mysql 数据库,查询其中的 user 表。
      • 创建用户:create user '用户名'@'主机名' identified by '密码'
        • localhost 表示本地主机,% (通配符)表示任意远程主机。
      • 删除用户:drop user '用户名'@'主机名'
      • 修改密码:update user set password = password('密码') where user='用户名' set password for '用户名'@'主机名'=password('密码')
      • 修改 root 用户密码:
        1. 在 cmd 中停止 mysql 服务:net stop mysql(管理员权限)。
        2. 使用无验证方式启动 mysql 服务:mysqld --skip-grant-tables
        3. 打开新的 cmd 窗口,输入 mysql 启动。
        4. 使用前述方式更改密码。
        5. 手动结束 mysqld 进程。
    • 权限管理:

      • 查询权限:show grants for '用户名'@'主机名'

      • 授予权限:grant 权限列表 on 数据库名.表名 to '用户名'@'主机名'

        • 权限列表包括 select、delete、update 等。

        • 授予所有权限:grant all on *.* to '用户名'@'主机名'

      • 撤销权限:revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名'


    iwehdio的博客园:https://www.cnblogs.com/iwehdio/
  • 相关阅读:
    [leetcode]Combination SumII
    NSum小结
    image 与 canvas 的相互转化
    $_SERVER 相关变量
    最近做的项目,总结一下。
    开始在博客园,写博客,先写点东西。
    Codeforces Round #584 C. Paint the Digits
    Codeforces Round #584 B. Koala and Lights
    Codeforces Round #584 A. Paint the Numbers
    HDU-2296-Ring(AC自动机, DP)
  • 原文地址:https://www.cnblogs.com/iwehdio/p/12330331.html
Copyright © 2020-2023  润新知