MySQL学习笔记7——视图和存储过程

视图和存储过程

  • 一、视图
    • 1、视图的作用
    • 2、如何操作视图和视图中的数据
    • 3、视图的优缺点
  • 二、存储过程
    • 1、如何创建存储过程
    • 2、调用存储过程
    • 3、修改和删除存储过程

一、视图

1、视图的作用

视图是一种虚拟表,我们可以把一段查询语句作为视图存储在数据库中,在需要的时候,可以把视图看做一个表, 对里面的数据进行查询。

创建视图语法结构:

CREATE [OR REPLACE]
VIEW 视图名称[(字段列表)]
AS 查询语句

现在,假设我们要查询一下商品的每日销售明细,这就要从销售流水表(demo.mytrans) 和商品信息表(demo.goodmaster)中获取到销售数据和对应的商品信息数据:

销售流水表(mytrans):
在这里插入图片描述
商品信息表(goodmaster):
在这里插入图片描述
在不使用视图的情况下,我们可以通过对销售流水表和商品信息表进行关联查询,得到每天商品销售统计的结果,包括销售日期、商品名称、每天销售数量的合计和每天销售金额的合计,如下所示:

SELECT
a.transdate,
a.itemnumber,
b.goodsname,
SUM(a.salesquantity) AS quantity, -- 统计销售数量
SUM(a.salesvalue) AS salesvalue -- 统计销售金额
FROM
demo.mytrans AS a
LEFT JOIN		-- 连接查询
demo.goodmaster AS b ON (a.itemnumber = b.itemnumber)
GROUP BY a.transdate , a.itemnumber;

在实际项目中,我们发现,每日商品销售查询使用的频次很高,而且经常需要以这个查询的结果为基础,进行更进一步的统计。

举个例子,超市经营者要查一下“每天商品的销售数量和当天库存数量的对比”,如果用一个SQL语句查询,就会比较复杂。历史库存表(inventoryhist)如下所示:
在这里插入图片描述
接下来我们的查询步骤会使用到子查询和派生表

  • 子查询:就是嵌套在另一个查询中的查询。
  • 派生表:如果我们在查询中把子查询的结果作为一个表来使用,这个表就是派生表。

这个查询的具体步骤是:

  1. 通过子查询获得单品销售统计的查询结果;
  2. 把第一步中的查询结果作为一个派生表,跟历史库存表进行连接,查询获得包括销售日期、商品名称、销售数量和历史库存数量在内的最终结果。
SELECT
a.transdate,
a.itemnumber,
a.goodsname,
a.quantity, 		-- 获取单品销售数量
b.invquantity		-- 获取历史库存数量
FROM
(SELECT					-- 子查询,统计单品销售
a.transdate,
a.itemnumber,
b.goodsname,
SUM(a.salesquantity) AS quantity,
SUM(a.salesvalue) AS salesvalue 
FROM
demo.mytrans AS a
LEFT JOIN
demo.goodmaster AS b ON (a.itemnumber = b.itemnumber)
GROUP BY a.transdate , a.itemnumber
) AS a -- 派生表,与历史库存进行连接
LEFT JOIN
demo.inventoryhist AS b
ON (a.transdate=b.invdate AND a.Itemnumber=b.Itemnumber);

可以看到,这个查询语句是比较复杂的,可读性和可维护性都比较差。针对这种情况,我们就可以使用视图。

我们可以把商品的每日销售统计查询做成一个视图,存储在数据库里,代码如下所示:

CREATE VIEW demo.trans_goodmaster AS		-- 创建视图
SELECT
a.transdate,
a.itemnumber,
b.goodsname,
SUM(a.salesquantity) AS quantity, -- 统计销售数量
SUM(a.salesvalue) AS salesvalue -- 统计销售金额
FROM
demo.mytrans AS a
LEFT JOIN		-- 连接查询
demo.goodmaster AS b ON (a.itemnumber = b.itemnumber) 	-- 与商品信息表关联
GROUP BY a.transdate , a.itemnumber;	-- 按照销售日期和商品编号分组

这样一来,我们每次需要查询每日商品销售数据的时候,就可以直接查询视图,不需要再写一个复杂的关联查询语句了。

我们来试试用一个查询语句直接从视图中进行查询:

SELECT * FROM demo.trans_goodmaster

如果我们要进一步查询"每日单品销售的数量与当日的库存数量的对比”,就可以把刚刚定义的视图作为一个数据表来使用。我们把它跟历史库存表连接起来,来获取销售数量和历史库存数量。就像下面的代码这样,查询就简单多了:

SELECT
a.transdate,
a.itemnumber,
a.goodsname,
a.quantity, 		-- 获取单品销售数量
b.invquantity		-- 获取历史库存数量
FROM
demo.trans_goodmaster AS a
LEFT JOIN
demo.inventoryhist AS b
ON (a.transdate=b.invdate AND a.Itemnumber=b.Itemnumber);

结果显示,这里的查询结果和我们刚刚使用派生表的查询结果是一样的。 但是,使用视图的查询语句明显简单多了,可读性更好,也更容易维护。

2、如何操作视图和视图中的数据

创建完了视图,我们还经常需要对视图进行一些操作,比如修改、查看和删除视图。同时,我们可能还需要修改视图中的数据。

操作视图:

-- 查看视图:
DESCRIBE 视图名;
-- 删除视图
DROP VIEW 视图名;

操作视图中的数据:

视图本身是一个虚拟表, 所以,对视图中的数据进行插入、修改和删除操作,实际都是通过对实际数据表的操作来实现的。

1、在视图中插入数据
假设商品信息表中的规格字段(specification) 被删除了,当我们尝试用INSERT INTO语句向demo.view_goodmaster视图中插入一条记录的时候,就会提示错误;

这是因为,只有视图中的字段跟实际数据表中的字段完全一样,MySQL才允许通过视图插入数据。刚刚的视图中包含了实际数据表所没有的字段"specification" ,所以在插入数据时,系统就会提示错误。

2、删除视图中的数据

DELETE FROM demo.view_goodmaster
WHERE itemnumber = 5;

3、修改视图中的数据

UPDATE demo.VIEW_goodmaster
SET salesprice=100
WHERE itemnumber=1;

可以发现视图和实际数据表都别修改了,所以不建议对视图进行更新操作。有一些情况下视图时不允许被更新的:

  • 视图中包含聚合函数:如果视图中包含SUM(), COUNT(), AVG(), MAX(), MIN()等聚合函数,则通常不允许直接更新。
  • 视图中包含连接(JOIN)操作:当视图是由多个表通过连接操作创建时,通常不能直接更新。
  • 视图中包含DISTINCT、GROUP BY、HAVING子句:这些查询元素通常也会使视图不可更新。
  • 视图中包含子查询:某些数据库系统不允许直接更新包含子查询的视图。
  • 视图基于不可更新的视图:如果视图是基于另一个不可更新的视图创建的,那么它本身也将是不可更新的。
  • 数据库管理系统的限制:不同的数据库管理系统对视图更新的支持程度不同。例如,MySQL的视图在某些情况下是不可更新的。

3、视图的优缺点

优点

  • 我们可以把视图看成一张表来进行查询, 所以在使用视图的时候,我们不用考虑视图本身是如何获取数据的,里面有什么逻辑,包括了多少个表,有哪些关联操作,而是可以直接使用。
  • 视图存储的是查询语句。所以在使用的时候,我们要通过定义视图的查询语句来获取结果集。而视图本身不存储数据,不占用数据存储的资源。
  • 视图具有隔离性。视图相当于在用户和实际的数据表之间加了一层虚拟表。用户不需要查询数据表,可以直接通过视图获取数据表中的信息。这样既提高了数据表的安全性,同时也通过视图把用户实际需要的信息汇总在了一起, 查询起来很轻松。
  • 视图的数据结构相对独立,即便实际数据表的结构发生变化,我们也可以通过修改定义视图的查询语句,让查询结果集里的字段保持不变。这样一来, 针对视图的查询就不受实际数据表结构变化的影响了。

在这里插入图片描述
缺点:我们在实际数据表的基础上创建了视图,如果实际数据表的结构变更了,我们就需要及时对相关的视图进行相应的维护。特别是当视图是由视图生成的时候,维护会变得比较复杂。

总结
在这里插入图片描述

二、存储过程

MySQL 存储过程是一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字和参数值来调用执行它。存储过程可以看作是对一系列 SQL 操作的封装和重用,它允许用户将复杂的 SQL 逻辑封装起来,通过简单的调用即可执行。

这样一来,不仅执行效率非常高,而且客户端不需要把所有的SQL语句通过网络发给服务器,减少了SQL语句暴露在网上的风险,也提高了数据查询的安全性。

存储过程的优点就是执行效率高,而且更加安全,不过,它也有着自身的缺点,那就是开发和调试的成本比较高,而且不太容易维护。

1、如何创建存储过程

CREATE PROCEDURE 存储过程名 ([IN | OUT | INOUT] 参数名称 类型) 程序体

举例:

DELIMITER //  
CREATE PROCEDURE SimpleProcedure(IN param1 INT, OUT param2 VARCHAR(255))  
BEGIN  -- 这里是存储过程的主体,可以包含任意的 SQL 语句  SET param2 = CONCAT('Hello, ', param1);  
END //  
DELIMITER ;

在上面的示例中,我们创建了一个名为 SimpleProcedure 的存储过程,它接受一个输入参数 param1(类型为 INT)和一个输出参数 param2(类型为 VARCHAR(255))。存储过程的主体部分使用 SET 语句将输出参数的值设置为 'Hello, ’ 和输入参数的拼接结果。

在创建存储过程时,我们使用了 DELIMITER 语句来更改语句分隔符。这是因为存储过程中可能包含多条 SQL 语句,而默认的语句分隔符是分号(;)。通过更改分隔符,我们可以确保整个存储过程被视为一个单独的语句块进行解析和执行。在存储过程定义结束后,再将分隔符恢复为默认的分号。

存储过程的参数

存储过程可以有参数,也可以没有参数。一般来说,当我们通过客户端或者应用程序调用存储过程的时候,如果需要与存储过程进行数据交互,就需要设置参数。否则,就不用设置参数。

参数有3种,分别是IN、OUT和INOUT。

  • IN表示输入的参数,存储过程只是读取这个参数的值。如果没有定义参数种类,默认就是IN,表示输入参数。
  • OUT表示输出的参数,存储过程在执行的过程中,把某个计算结果值赋给这个参数,执行完成之后,调用这个存储过程的客户端或者应用程序就可以读取这个参数返回的值了。
  • INOUT表示这个参数既可以作为输入参数,又可以作为输出参数使用。

存储过程的程序体

程序体中包含的是存储过程需要执行的SQL语句,一般通过关键字BEGIN表示SQL语句的开始,通过END表示SQL语句的结束。

查看存储过程

我们可以通过SHOW CREATE PROCEDURE存储过程名称,来查看刚刚创建的存储过程:

SHOW CREATE PROCEDURE SimpleProcedure;

2、调用存储过程

要调用前面创建的 SimpleProcedure 存储过程,需要按照以下步骤进行:

  • 设置会话变量:对于输出参数 param2,需要先声明一个会话变量来接收它的值。在 MySQL 中,你可以使用 @ 符号来声明用户定义的会话变量。
  • 调用存储过程:使用 CALL 语句来调用存储过程,并传递必要的参数值。
  • 检索输出参数的值:调用存储过程后,你可以通过查询之前设置的会话变量来获取输出参数的值。
-- 声明一个会话变量来接收输出参数的值  
SET @output_value = '';  -- 调用存储过程,传入一个输入参数值,并接收输出参数的值  
CALL SimpleProcedure(123, @output_value);  -- 查询会话变量的值,以检索存储过程的输出  
SELECT @output_value AS output_param;

在这里插入图片描述

3、修改和删除存储过程

在 MySQL 中,你不能直接修改一个已经存在的存储过程。需要先删除原有的存储过程,然后创建一个新的存储过程来替换它。这样做的原因是 SQL 本身并没有提供直接修改存储过程的语法。

-- 删除原有的存储过程:
DROP PROCEDURE IF EXISTS SimpleProcedure;

这条语句会检查 SimpleProcedure 存储过程是否存在,如果存在则删除它。IF EXISTS 是可选的,用于避免在存储过程不存在时引发错误。

-- 创建新的存储过程:
DELIMITER //  
CREATE PROCEDURE SimpleProcedure(IN param1 INT)  
BEGIN  -- 我们可以简单地将输入参数的值插入到某个表中INSERT INTO some_table (some_column) VALUES (param1);  
END //  
DELIMITER ;-- 调用这个存储过程
CALL SimpleProcedure(123);

注意事项:

  • 在执行 DROP PROCEDURE 之前,请确保没有其他数据库会话正在使用该存储过程,否则可能会导致错误。
  • 修改或删除存储过程可能会影响依赖于这些过程的应用程序或脚本,因此在执行这些操作之前,最好先通知相关团队或进行充分的测试。
  • 在生产环境中,对存储过程的修改和删除应该谨慎进行,并遵循适当的变更管理流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/2358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

liqo学习及安装,k8s,kubernetes多集群互联

先按照官方的教程在虚拟机安装学习 在开始以下教程之前,您应该确保您的系统上安装了以下软件: Docker,容器运行时。Kubectl,Kubernetes 的命令行工具。 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.…

基于Python利用zhconv模块进行简繁体字转换

在处理中文文本时,简繁体字之间的转换是一项常见的任务。Python提供了许多库来实现这个目的,其中之一就是zhconv。zhconv是一个Python库,提供了简体字和繁体字之间的转换功能。本教程将向你展示如何使用zhconv模块来实现简繁体字的互转&#…

Redis底层数据结构之Dict

目录 一、概述二、Dict结构三、Dictht结构四、DictEntry结构五、核心特性 上一篇文章 reids底层数据结构之quicklist 一、概述 Redis 的 Dict 是一个高效的键值对映射数据结构,采用双哈希表实现以支持无锁的渐进式 Rehash,确保扩容或缩容时的高效性能。…

想冲宇宙厂,直接挂了。。。

宇宙厂实际是字节,这个称呼是因为字节跳动主宰了宇宙内一切App,有点家大业大的意思。 今天分享一位字节春招凉经,问了一些数据库和Java八股,没出算法题,直接挂了,竟然最喜欢出算法题的字节,这次…

iptables实现docker容器动态端口映射实操

背景 之前在《Docker 动态修改容器端口映射的方法》一文中,说明了如何使用修改配置和加防火墙规则实现动态端口映射。但是没有具体分享加防火墙实现动态端口映射的实际案例。今天就分享一下实际操作案例,供大家参考。 分析 动态端口映射的用途 容器端口…

(2024)Visual Studio的介绍、安装与使用

Visual Studio介绍 1.Visual Studio是什么? Visual Studio是微软公司推出的一款开发工具包系列产品,它是一个基本完整的开发工具集,为软件开发者提供了整个软件生命周期中所需的大部分工具。 2.Visual Studio的定义 Visual Studio是美国微软公…

网盘_游戏_博客自动化部署(Nginx多项目部署)

目录 一.前提介绍 二.环境介绍 三.自述(脚本) 四.关于Nginx多项目部署 一.前提介绍 在我之前的博客里详细介绍了上述项目的部署,那么如何使用简单脚本自动部署和使用Nginx多项目部署是本文来介绍的基础篇章。 二.环境介绍 CentOS Linux…

fawawf

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…

【Linux】文件目录及路径表示

1. Linux目录结构 在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。 /etc: 这个是系统中的配置文件,如果更改了该目录下的某个文件可能会导致系统不能启动。 /bin, /sbin, /usr/bin, /usr…

java泛型介绍

Java 泛型是 JDK 5 引入的一个特性,它允许我们在定义类、接口和方法时使用类型参数,从而使代码更加灵活和类型安全。泛型的主要目的是在编译期提供类型参数,让程序员能够在编译期间就捕获类型错误,而不是在运行时才发现。这样做提…

小程序AI智能名片S2B2C商城系统:解锁内容深耕新境界,助力品牌企业高效定制内容策略

在数字化时代,内容营销已成为品牌企业获取市场份额、增强用户黏性的关键武器。然而,面对海量的互联网信息和复杂多样的社交媒体平台,如何有效地深耕内容,成为众多品牌企业面临的难题。 传统的内容分类与识别方式,往往依…

【数据分析面试】28. 20个Python问答题 (入门级考察:基础操作、数据处理与分析统计)

今天的20个问题考察了 Python 的基础能力,包括数据结构、基本操作、数据处理、数据分析和统计等方面。无论是从事数据分析、机器学习还是其他数据相关工作,这些都是必不可少的基础技能。 数据结构与基础操作: 什么是 Pandas 库?它…

中兴5G随身wifi怎么样?中兴5G随身wifiVS格行5G随身wifi对比测评!公认最好的随身WiFi的格行随身WiFi真实测评!随身WiFi哪个品牌好?

随着各大品牌5G随身wifi的横空出世,其中中兴和格行5G随身wifi的呼声越来越高,那么性能上谁更胜一筹?套餐费用谁更亲民?售后保障谁更到位?今天就来一个全方位测评对比! 一,首先是设备的整体外观&…

uniapp:小白1分钟学会使用webSocket(可无脑复制)

uni.connectSocket() uni.$emit页面通信 项目中使用uni.connectSocket()创建webSocket的总结,代码可无脑复制,直接使用。 1、main.js 引入vuex import store from ./store; Vue.prototype.$store store;vuex中封装webSocket 2、vuex的:index…

linux autogroup

一:概述 对于linux autogroup的作用,很多同学可能是听说过,但,并未验证过。 考虑下面场景,开两个terminal,T1和T2,在T1中运行进程P1,P1开启9个线程编译代码,在T2中运行…

yield函数怎么理解?

目录 白话系列: 例子🌰: 什么叫暂停 yield和next搭配使用 例子🌰: 白话系列: 可以暂停,可以生成,next一个,yield一个 例子🌰: def generat…

CUDA线程管理

核函数在主机端启动时,执行会转移到设备上,并且将控制权转移回主机。当核函数在GPU上运行时,主机可以运行其他函数。因此,主机与核函数是异步的。 此时,设备端也就是GPU上会产生大量的线程,并且每个线程都…

(七)小案例银行家应用程序-申请贷款-some方法和every方法

some方法 ● 我们先回顾一下includes方法 console.log(movements.includes(-130));只要数组中存在-130这个值,就会返回true,否则就会返回flase ● 而some方法只要达成某一个条件就会返回true,否则就返回flase const someMethod movement…

stm32开发之threadx之modulex模块文件的生成脚本项目

前言 为了保证在window上运行,且体积小的问题,所以采用c语言编写生成脚本,将相关路径由json文件进行配置,使用了一个cjson库进行解析项目构建使用的是cmake 项目代码 CMakeLists文件 cmake_minimum_required(VERSION 3.27) project(txm_bat_script C…

Day13-Java进阶-IO字节流及其练习题

1. IO流介绍 2. IO 流体系结构 字节流读取纯文本文件会出现乱码问题 2.1 FileOutputStream 字节输出流 package com.itheima.stream.output;import java.io.FileOutputStream; import java.io.IOException;public class FileOutputStreamDemo3 {/*IO流的异常处理方式: jdk7版本…