🔗 联结表
[!quote] 联结表
联结表 是一种将两个或多个表中的数据通过某些共同的值关联起来的操作
[!hint] 大多数 DBMS,处理联结的速度 >> 子查询
联结表分为:
- 【内联结】:结果只包含所有参与联结的表中,都有匹配记录的行
- 【自联结】:将一个表视为两个不同的表进行联结
- 【外联结】:允许从至少一个表中选择所有记录,即使这些记录在另一个表中没有匹配的记录
[!hint] 笛卡尔积 如果在联结时,没有加上限制条件,则是把 表 A 的每一行匹配 表 B 的每一行,所以如果此种情况
SELECT *时,则查询的行数 = 表 A 行数 * 表 B 行数
内联结
隐式内联结
SELECT 字段 FROM 表1,表2 WHERE 条件;【表 1 和表 2 就通过了WHERE联结在了一起】显示内联结
SELECT 字段 FROM 表1 [INNER] JOIN 表2 ON 联结条件;
select user.id, user.name, user.age, table_name.产品ID
from user
INNER JOIN table_name ON table_name.id = user.id;
---
|id|name|age|
|:-:|:-:|:-:|
|123|陈冠希|45|
|11|刘诗诗|14|
|444|吴彦祖|4|
+
|产品ID|id|
|:-:|:-:|
|乌鸦 |444|
|狗|11|
|老虎|123|
↓
|id|name|age|产品ID|
|:-:|:-:|:-:|:-:|
|123|陈冠希|45|老虎|
|444 |吴彦祖|4|乌鸦|
|11 |刘诗诗|14|狗|自联结
//使用自联结的方式来实现
SELECT c1.id, c1.name, c1.contact
FROM customers AS c1,
customers AS c2
WHERE c2.contact = 'jim' //经过这个条件筛选过后,c2表中只剩下一条记录
AND c1.name = c2.name; //c1表中的name与c2表中的那一条记录进行比较
//如果使用子查询的方式来实现:
SELECT id, name, contact
FROM customers
WHERE name = (SELECT name FROM customers WHERE contact = 'Jim');
---
|id|name|contact|
|:-:|:-:|:-:|
|100|Fun123|Jim|
|101|Fun566|Tom| × 2
|102|Fun123|Mike|
|103|Fun578|July|
↓
|100|Fun123|Jim|
|102|Fun123|Mike|外联结
- 左外联结
SELECT 字段列表 FROM 表A LEFT JOIN 表B ON 联结条件;返回左表中所有的行,以及右表中满足条件的行
SELECT customers.id, orders.numbers
FROM customers
LEFT JOIN orders ON customers.id = orders.id;
---
|id|name|contact|
|:-:|:-:|:-:|
|100|Fun123|Jim|
|101|Fun566|Tom|
|102|Fun123|Mike|
|103|Fun578|July|
+
|id|numbers|
|:-:|:-:|
|101|null|
|102 |9|
|103 |229|
↓
|id|numbers|
|:-:|:-:|
|100|null|
|101|null|
|102|9|
|103|229|- 右外联结:返回右表中所有的行,以及左表中满足条件的行【
一般不使用】
视图
[!quote] 视图
视图 是一组定义好的查询语句,可以看成是一张虚拟的表,而不是一个实际存储的数据集,
优点
- 可以使用视图封装某一组复杂的语句,进行重用,简化复杂的 SQL 操作
缺点
- 视图不能索引
- 视图不能有关联的触发器:视图本身不能包含触发器,因为触发器是与表关联的
视图只能被 `SELECT` ,不能进行其他的 CUD 操作
- 创建视图
CREATE VIEW 视图名 AS 语句;
CREATE VIEW ProductCustomers AS
SELECT cust_name, cust_contact, prod_id
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num;删除视图
DROP VIEW 视图名;使用视图
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';避免使用多个联结创建复杂的视图,过滤创建复杂的视图,或者嵌套视图,这样会导致性能下降
物化视图
[!quote] 物化视图 物化视图 是存储了实际数据的表,需要定期刷新以保持数据的最新状态,用于性能优化,
特别是在需要频繁访问复杂查询结果的场景中
- 可以包含索引
创建物化视图需要数据库或表级别的 CREATE 权限,刷新物化视图需要 INSERT 权限,以及物化视图所涉及的所有表的相关列(或整个表)的 SELECT 权限。创建物化视图时可以使用普通表定义中的参数,如分区键、分布键、索引等,并且可以定义索引来提高查询性能。
MySQL 的物化视图可以通过创建一个实际的表来实现,这个表存储了需要查询的数据,并且可以定期刷新以保证数据的准确性。物化视图的刷新可以通过手动触发或使用触发器、事件来实现增量刷新
[!hint] 区分 视图 与 存储过程
- 视图 只是一组
SELECT语句,帮你简化操作,在你需要时执行,所以视图只能SELECT,不能CUD- 存储过程 是一组 SQL 语句【CRUD】,你可以传入参数,它可以帮你实现一组行为,
类比 Java 中的函数
存储过程
[!quote] 存储过程 存储过程 是一组预编译的 SQL 语句【
CRUD】,存储在数据库中以便重复使用。存储过程就像是定义了一组复杂的行为,你可以方便地调用,类似 Java 中的把复杂的逻辑封装为代码
- 优点
- 提高性能:存储过程在数据库服务器上执行,减少了通信次数
- 安全:存储过程封装好了操作,应用程序只需要传入参数不执行 SQL,执行 SQL 交给数据库服务器的存储过程来执行,防止 SQL 注入
- 缺点
- 存储过程不可移植
- 编写起来更加复杂
https://www.runoob.com/w3cnote/mysql-stored-procedure.html
存储过程的主要用途:
- 复杂逻辑处理: 存储过程可以包含复杂的业务逻辑和控制流程,例如条件判断、循环、异常处理等,从而减少在应用程序中处理这些逻辑的复杂性。
- 减少网络流量: 将一组 SQL 语句打包在一个存储过程中,可以减少应用程序和数据库之间的数据传输量,从而提高整体性能