ToB企服应用市场:ToB评测及商务社交产业平台

标题: MySQL数据库设计概念(多表查询&事务操作) [打印本页]

作者: 天空闲话    时间: 2022-6-24 10:02
标题: MySQL数据库设计概念(多表查询&事务操作)
每天进步一点点



数据库设计概念

数据库设计简介

1.数据库设计概念

2.数据库设计步骤

3.表关系简介

在数据库中,表总共存在三种关系,真实的数据表之间的关系:多对多关系、一对多(多对一)、一对一(极少),(一对一关系就是我们之前学习的Map集合的key-value关系)
表关系(多对多)

1.多对多

2.外键约束

3.外键约束语法
  1. -- 关键字解释:
  2. constraint: 添加约束,可以不写
  3. foreign key(当前表中的列名): 将某个字段作为外键
  4. references 被引用表名(被引用表的列名) : 外键引用主表的主键
  5. -- 创建表时添加外键约束
  6. CREATE TABLE 表名(
  7.    列名 数据类型,
  8.    …
  9.    [CONSTRAINT] [外键名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名)
  10. );
  11. -- 建完表后添加外键约束
  12. ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
  13. -- 删除约束
  14. ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
复制代码
4.创建外键约束
  1. -- 订单表
  2. CREATE TABLE tb_orders
  3. (
  4.     id           int primary key auto_increment,
  5.     payment      double(10, 2),
  6.     payment_type TINYINT, -- 0 微信支付  1 支付宝支付
  7.     status       TINYINT  -- 0 未付款  1 已经支付
  8. );
  9. -- 商品表
  10. CREATE TABLE tb_goods
  11. (
  12.     id    int primary key auto_increment,
  13.     title varchar(100),
  14.     price double(10, 2)
  15. );
  16. -- 订单商品中间表
  17. CREATE TABLE tb_order_goods
  18. (
  19.     id       int primary key auto_increment,
  20.     order_id int, -- 外键,来自于订单表的主键
  21.     goods_id int, -- 外键,来自于商品表的主键
  22.     count    int,  -- 购买商品数量
  23.     foreign key(order_id) references tb_orders(id),
  24.     foreign key(goods_id) references tb_goods(id)
  25. );
复制代码

5.外键级联
在修改和删除主表的主键时,同时更新或删除从表的外键值,称为级联操作

6.总结
   1.为何要引用外键约束?
  
  2.添加外键约束语法?
  
  3.有了外键约束操作数据注意事项?
  
  表关系(一对多)

一对多(多对一)


表关系之一对一

一对一


多表查询


准备数据
  1. -- 价格
  2. create table price
  3. (
  4.     id    int primary key auto_increment,
  5.     price double
  6. );
  7. -- 水果
  8. create table fruit
  9. (
  10.     id       int primary key auto_increment,
  11.     name     varchar(20) not null,
  12.     price_id int,
  13.     foreign key (price_id) references price (id)
  14. );
  15. -- 数据
  16. insert into price
  17. values (1, 2.30);
  18. insert into price
  19. values (2, 3.50);
  20. insert into price
  21. values (4, null);
  22. insert into fruit
  23. values (1, '苹果', 1);
  24. insert into fruit
  25. values (2, '橘子', 2);
  26. insert into fruit
  27. values (3, '香蕉', null);
复制代码
笛卡尔积现象

1.什么是笛卡尔积现象

需求:查询两张表中关于水果的信息,要显示水果名称和水果价格
表设计原则:将价格的主键作为水果的外键
  1. -- 多表查询语法(同时查询多个表获取到需要的数据)
  2. select * from 表名1,表名2;
  3. -- 查询价格(我们向查询水果对应的价格,需要将水果表和价格表同时进行查询;)
  4. select * from fruit,price;
复制代码
查询结果:

2.笛卡尔积产生原因

fruit表中的每一条记录,都和price表中的每一条进行匹配连接。所得到的最终结果是:fruit表中的条目数乘以price表中的数据的条目数。
将fruit表的每行记录和price表的每行记录组合的结果就是笛卡尔积
3.如何避免笛卡尔积
解决上述查询的方案:在查询两张表的同时添加条件进行过滤,比如fruit表的id和必须和price表的id相同
  1. -- 条件过滤笛卡尔积
  2. select * from fruit,price where fruit.price_id=price.id;
复制代码

内连接查询

1.什么是内连接
   内连接查询又称为交集查询,也就是查询只显示满足条件的数据
  2.显示内连接
显示内连接:使用INNER JOIN...ON语句,可以省略INNER关键字
  1. -- 语法核心
  2. select * from 表名1 inner join 表名2 on 条件;
  3. -- 或者
  4. select * from 表名1 join 表名2 on 条件;
复制代码
3.隐式内连接
看不到JOIN关键字,条件使用WHERE指定
  1. select 列名,列名,... from 表名1,表名2 where 表名1.列名=表名2.列名;
复制代码
4.示例
查询水果的价格
  1. -- 隐式内连接
  2. select * from fruit,price where fruit.price_id=price.id;
  3. -- 显式内连接
  4. select * from fruit inner join price on fruit.price_id=price.id;
复制代码

查询苹果的信息,显示苹果的id,名字,价格
  1. -- 方式1
  2. select fruit.id, fruit.name, price.price
  3. from fruit,
  4.      price
  5. where fruit.price_id = price.id
  6.   and fruit.name = '苹果';
  7. -- 方式2
  8. select fruit.id, fruit.name, price.price
  9. from fruit
  10.          inner join
  11.      price
  12.      on fruit.price_id = price.id
  13.          and fruit.name = '苹果';
复制代码

5.总结
1.内连接作用?

2.什么是隐式内连接和显示内连接?

3.内连接查询步骤?

外连接查询

1.左外连接

语法格式:
  1. select * from 表1 left [outer] join 表2 on 条件;
复制代码
说明:

练习:
不管能否查到水果对应价格,都要把水果显示出来
  1. -- 左外连接查询
  2. select * from fruit left outer join price on fruit.price_id=price.id;
复制代码

2.右外连接

语法格式:
  1. select * from 表名1 right [outer] join 表名2 on 条件;
复制代码
说明:

练习:
不管能否查到价格对应的水果,都要把价格显示出来
  1. select * from fruit right outer join price on fruit.price_id=price.id;
复制代码

总结:
1.掌握左外连接查询格式?

2.左外连接查询特点?

3.掌握右外连接查询格式?

4.右外连接查询特点?

嵌套查询(子查询)

1.什么是子查询
一条查询语句结果作为另一条查询语法一部分。
  1. SELECT 查询字段 FROM 表 WHERE 条件;
  2. 举例:
  3. SELECT * FROM employee WHERE salary=(SELECT MAX(salary) FROM employee);
复制代码
说明:子查询需要放在()中
三种子查询情况:单行单列、多行单列、多行多列。
2.单行单列
子查询结果是单列,在WHERE后面作为条件
  1. SELECT 查询字段 FROM 表 WHERE 字段=(子查询);
复制代码

通常使用比较运算符: > 、>= 、成功–>提交事务开启事务–>执行SQL语句–>失败–>回滚事务
</ul>
演示案例:演示提交事务,a给b转账100元
  1. -- IN表示在数值中
  2. SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);
复制代码

案例演示:演示回滚事务,a给b转账100元
  1. SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;
复制代码

注意:

自动提交事务

MySQL的每一条DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,执行完毕自动提交事务,MySQL默认开始自动提交事务。自动提交,通过修改mysql全局变量autocommit进行控制。
通过以下命令可以查看当前autocommit模式
  1. # 创建账号表
  2. create table account(
  3.         id int primary key auto_increment,
  4.         name varchar(20),
  5.         money double
  6. );
  7. # 初始化数据
  8. insert into account values (null,'a',1000);
  9. insert into account values (null,'b',1000);
复制代码

设置自动提交的参数为OFF
  1. -- 1.开启事务
  2. start transaction;
  3. -- 2.执行sql语句
  4. update account set money=money-100 where name='a';
  5. update account set money=money+100 where name='b';
  6. -- 3.提交事务
  7. commit;
复制代码

案例演示
  1. -- 自动提交事务:每条sql语句就是一个事务,那么执行一条sql语句就会提交一次事务-- mysql数据库就是自动提交事务-- a给b转账100元update account set money=money-100 where name='a';update account set money=money+100 where name='b';-- 查看mysql是否自动提交事务-- autocommit的值是on表示自动提交事务,值是off表示关闭自动提交事务# 创建账号表
  2. create table account(
  3.         id int primary key auto_increment,
  4.         name varchar(20),
  5.         money double
  6. );
  7. # 初始化数据
  8. insert into account values (null,'a',1000);
  9. insert into account values (null,'b',1000);-- 我们可以使用命令临时设置mysql变为手动提交事务,即将自动提交事务关闭-- 下次重新连接mysql依然是自动提交事务set autocommit = 0; -- 0 表示关闭自动提交事务 1表示开启自动事务update account set money=money-100 where name='a'
复制代码
注意:
1)MySql默认自动提交。即执行一条sql语句提交一次事务。
2)设置autocommit为off状态,只是临时性的,下次重新连接mysql,autocommit依然变为on状态。
3)如果设置autocommit为off状态,那么当我们执行一条sql语句,就不会自动提交事务,重新启动可视化工具,数据并没有改变。
4)如果设置autocommit为on状态,如果我们先执行start transaction 然后在执行修改数据库的语句:
  1. show variables like '%commit%';
复制代码
那么此时就表示上述修改数据库的sql语句都在同一个事务中,此时必须手动提交事务,即commit;
换句话说,如果我们手动开启事务start transaction那么此时mysql就不会自动提交事务,必须手动提交事务。
5)如果设置autocommit为on状态,如果我们不执行start transaction 直接执行修改数据库的语句:
  1. show variables like '%commit%';
复制代码
那么此时mysql就会自动提交事务,即上述每条sql语句就是一个事务
事务原理和四大特征

事务原理


原理说明
事务的四大特征

事务的四大特征(ACID)
数据库的事务必须具备ACID特征,ACID是指Atomicity(原子性)、Consistensy(一致性)、Isolation(隔离性)和Durabiliyt(持久性)
隔离性(Isolation)
多个用户并发的访问数据库时,一个用户的事务不能被其他用户的事物干扰,多个并发的事务之间相互隔离

持久性(Durability)
指一个事务一旦被提交,它对数据库的改变是永久性的,哪怕数据库发生异常,重启之后数据依然会存在

原子性(Atomicity)
指事务包装的一组sql语句(一组业务逻辑)是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
一致性(Consistency)
一致性是指数据处于一种语义上有意义且正确的状态;
事务一致性是指事务执行的结果必须是使数据从一个一致性状态变到另一个一致性状态。
事务的成功与失败,最终数据库的数据都是符合实际生活的业务逻辑。一致性绝大多数依赖业务逻辑和原子性

事务的并发访问引发的三个问题(面试)

事务在操作时的理想状态:多个事务之间互不影响,如果隔离级别设置不当就可能引发并发访问问题
并发访问的问题含义脏读一个事务读取到了另一个事务中尚未提交的数据。最严重,杜绝发生。不可重复读一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是不一致的,这是事务update时引发的问题幻读(虚读)一个事务内读取到了别的事务插入或者删除的数据,导致前后读取记录行数不同。这是insert或delete时引发的问题1.脏读:指一个事务读取了另外一个事务未提交的数据。(非常危险)

2.不可重复读:在一个事务内多次读取表中的数据,多次读取的结果不同。

3.幻读(虚读):一个事务内读取到了别的事务插入或者删除的数据,导致前后读取记录行数不同

4.总结

事务的隔离级别

通过以上问题演示,我们发现如果不考虑事务的隔离性,会遇到脏读、不可重复读和虚读等问题。所以在数据库中我们要对上述三种问题进行解决。MySQL数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况。
事物隔离级别
上面的级别最低,下面的级别最高。是表示会出现这种问题,否表示不会出现这种问题。
级别名字隔离级别脏读不可重复读幻读数据库默认隔离级别1读未提交read uncommitted是是是2读已提交read committed否是是Oracle和SQL Server3可重复读repeatable read否否是MySQL4串行化serializable否否否安全和性能对比
<ul> 安全: 串行化>可重复读>读已提交>读未提交
  
性能: 串行化




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4