MySQL数据分析进阶(八)存储过程
※食用指南:文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记,笔记整理比较粗糙,主要目的自存为主,记录完整的学习过程。(图片超级多,慎看!)
【中字】SQL进阶教程 | 史上最易懂SQL教程!10小时零基础成长SQL大师!!
https://www.bilibili.com/video/BV1UE41147KC/?spm_id_from=333.1007.0.0&vd_source=b287f1f4a1fa54cc438e31a0f87ef4e2
第八章:存储过程
1、WHAT ARE STORED PROCEDURES——什么是存储过程
不建议在应用代码里写语句:会让应用代码很混乱且难以维护
①在使用C#、Java或者Python开发应用
如果把Java代码和SQL混在一起,那么SQL代码介入会让应用代码很混乱和难以维护
②一些C#、Java这样的编程语言需要编译工作
在这类应用代码里写SQL查询,一旦发现需要修改其中的查询,就必须重新编译应用代码才能生效。所以每次修改SQL代码都需要重新编译或者可能重新部署应用代码
解决方法:将SQL代码储存在它应属的数据库里——存储过程或函数中
存储过程Stored Procedure:一个包含一堆SQL代码的数据库对象
存储过程Stored Procedure的优势:

①Store and organize SQL(存储和管理SQL)
在应用代码里,调用这些过程来获取或保存数据,使用存储过程来存储和管理SQL代码
②Faster execution(更快速执行)
大多数DBMS可以对存储过程里的代码做一些优化,因此存储过程里的SQL代码有时执行起来更快
③Data security(数据安全性)
取消对所有表的直接访问权限,让很多操作如插入、更新和删除数据由存储过程来完成,然后可以指定能够执行特定存储过程的某一人,从而限制用户对我们数据的操作范围(防止一些用户删除数据)
2、CREATING A STORED PROCEDURE——创建一个存储过程
把这个查询存在存储过程里

①get_clients,使用小写字母并用下划线分隔,是MySQL开发者通用的
②BEING和END关键字之间的内容成为存储过程的主体(body)
③通常创建的存储过程有好几条语句(SELECT部分),每条(包含一条)语句都需要分号终结
其他的DBMS,如SQL Server可能就不需要
DELIMITER重新定义分割符:让存储过程不会到clients时报错

$$视为新的分隔号,把所有的语句当成一个整体;
最后再用DELIMITER ;把符号还回分号
🔺DELIMITER后面要加空格
其他的DBMS,如SQL Server不需要改动默认分隔符
执行后刷新


一般来说,我们会用C#、Java、Python等应用代码调用存储过程,但有时想用SQL代码调用存储过程,使用CALL即可
![]()
练习:


3、CREATING PROCEDURES USING MAYSQLWORKBENCH——使用MYSQL工作台创建存储过程
更为简单的存储工程创建方式:
导航面板→右击存储过程文件夹→创建一个存储过程

在这个窗口就不用担心改默认分隔符,重点放在SQL语句

MySQL会默认添加反引号,防止SQL关键字的名称冲突

编写完Apply,MySQL自动生成SQL语句,再次Apply



4、DROPPING STORED PROCEDURES——删除存储过程
出了错的或者想要重新创建存储过程的方法:
执行后即刻消失,再次执行就会报错(删除一个并不存在的过程)
![]()
可以使用IF EXISTS关键字来防止错误出现(参考view)
![]()
AGAIN:最好把删除和创建每一个存储过程的代码存储在不用的SQL文件中,并把文件放在GIT源代码控制下,可以和其他组员共享GIT存储库,任何人都可以在自己的电脑上使用所有视图和存储过程再建数据库
安全重建:删除检查是否有同名的存储过程存在,有的话就删掉,再重新创建
(并存到了新stored_procedures文件夹,名为client_id)

5、PARAMETERS——参数
在存储过程中添加参数
一般使用参数为存储过程传递值,也可以为调用程序赋值

state CHAR (2):有两个字符的字符串
VARCHAR:可改变长度的字符串(存储姓名、电话号码、信息),一般能确定字符串有固定长度才使用
WHERE state = state:这里不会起任何作用因为在用它本身列的值对比(无论如何都是对的)
🔺需要把这两个state(state这一列的值、定义的state这个系数)区分开:
①加前缀p(parameter)
![]()
②加后缀_ param
![]()
③不变动,给表格起别名
![]()

调用情况:

如果不提供任何值,将会出现错误,因为MySQL中所有系数都是必填的
练习:

Invoices表中client_id系数为INT(整数)


完成后调用,输入你的系数(即哪位客户)


6、PARAMETERS WITH DEFAULT VALUES——带默认值的参数
为系数配置默认值
在get_clients_by_state制定一个规则:如果存储过程调用这无法明确具体在那个state,就默认返回CA的客户
①使用IF函数
IF函数结尾需要用END IF:告诉MySQL语句该到哪里结束

②创建完毕使用空值调用这个过程——验证

③再改变一下规则:不只是返回位于CA的客户,而是返回所有客户

当输入NULL

当输入CA

④将两段查询合并为一段
IFNULL(state,C.state):如果第一个值是空值,就返回第二个值

练习:

INT、TINYINT都是整数
INT:占用4个字节,可以存储更大的数字-
TINYINT:占用1字节的内存,可以存储0-255的数字
client_id、payment_method_id 这两个系数都不是必填的,
^ 如果传递NULL,过程应该能够返回数据库里的所有付款记录
^ 如果提供client_id,则返回这个客户的payment_method_id
^ 如果这两个系数都赋值,就返回指定客户使用付款方式支付的所有付款
AND:两个条件都需要满足
payment_mothod_id:是参数名称,可以与列名不同

Arguments实参:提供给形参的值
Parameters形参:占位符,过程或函数中的小小坑位
如上定义了两个形参:client_id、payment_method_id
7、PARAMTETER VALIDATION——参数验证
使用过程插入、更新和删除数据
创建一个过程更新发票过程中学习参数验证,确保过程不会意外地往数据库存储错误数据
DECIMAL(9,2):小数数据类型
第一个参数代表位数,第二个参数是小数点后的位数:最多9位数,小数点后两位
只想更新i.payment_total 、i.payment_date
不想意外更新invoice表中的number,invoice_date等

之前数据:

调用执行


如果数值为负数,则会出现不合理的数据
![]()

❗如何验证传递给这个存储过程的参数:
SIGNAL语句:标志或者引发错误(像其他编程语言中抛出异常)
查找错误的完整列表在此处查询:sqlstate errors
前两个字母界定了错误类别
22:数据异常
22003:在存储过程中,处理超位值
SIGNAL SQLSTATE '22003':这里的22003是字符串,而不是数字

确认后再次执行,弹出错误提醒
![]()
综上:在做任何数据变动前线检查存储过程系数很有帮助
但如果写太多参数验证,也会使存储过程变得很复杂并难以维护
这里的payment_amount本身就是不允许有空值,即便传递了空值,MySQL自动标注这一错误,不需要再编写

要尽量利用最少的验证逻辑,只保留最最关键的
应该从用户端接受输入信息,再在应用中使用更多验证(前后端中进行验证)
相比访问数据库,在应用在检测和报告错误会更快捷
把参数验证作为终极备选方案,以防止有人没有通过应用直接调用了存储过程
8、OUTPUT PARAMETERS——输出参数
用参数来给调用程序返回值
创建后验证:




也可通过参数获取这些值
使用TINYINT或者INT,具体根据未支付发票数量决定

默认情况下,存储过程的所有这些系数都是输入参数,也就是只能在给过程传递值的时候才可以使用它们,所以需要给两个参数附上OUT关键字前缀,就会把参数标记为输出参数

SELECT COUNT(*),SUM(invoice_total):取读数据
INTO invoices_count,invoices_total:复制到这些输出参数
![]()

代码解释
①用户定义变量:set @invoices_count = 0;、set @invoices_total = 0;
变量就是可以用来存储单一值的对象
@作为前缀来定义变量,调用过程中传递这些变量
②(3, @invoices_count, @invoices_total);
第一个参数3,即为客户3,后面连个参数就是先前定义的变量
③select @invoices_count, @invoices_total;
调用过程后,需要用选择语句来取读这些值,并在此显示

使用输出参数需要在读取数据上花精力,除非有足够的动机,尽量避免使用
9、VARIABLES——变量
User or session variables :用户或者会话变量
SET语句定义,@符号作为前缀
@invoices_count = 0;
通常在调用有输出参数的存储过程时使用这些变量(传递变量,获取输出参数值)
变量在整个客户会话过程中被保存,客户从MySQL断线时,变量又被清空
Local variables:本地变量(局部变量)
不会在整个客户端会话过程中被保存,一旦存储过程完成执行任务,这些变量就会被清光
一般在存储过程中执行计算任务
①设定一个商业规则

此处就可使用本地变量,在过程中定义这些本地变量,能轻易地计算这个公式
②在BEGIN语句后声明变量
DECLARE:是在复合语句中声明变量地指令,在过程中定义的变量并不是真正的定义。
只是在BEGIN/END块内定义了而已(也就是形参)

③第二、三个变量不设置默认值,用选择语句来设定

④计算风险因素
SET设计变量的值

以上为如何在存储过程中声明并使用本地变量
这些本地变量只有在存储过程中才有意义,只要声明它们,就可以被使用了
然后一旦我们执行完毕存储过程,就被抹去了

(结果错了,但暂时找不到原因)
10、FUNCTIONS——函数
创建自己的函数
函数只能返回单一值,比起存储过程,无法返回拥有多行和多列的结果集
如上节,创建函数计算每位客户的风险因素

RETURNS:明确了这个函数返回的值的类型,可以是INT、INTEGER或者任何其他MySQL中的数据类型
在RETURNS设置函数属性(每个MySQL至少要有一个属性)
DETERMINISTIC(确定性):如果给予这个函数同样的一组值,它永远会返回一样的值
在不想根据数据库中的数据返回值的时候很有用
READS SQL DATA(读取SQL数据):函数中会配置选择语句,以读取一些数据
MODIFIES SQL DATA(修改SQL数据):函数中有插入、更新或者删除函数
可以同时有多种属性,既取读又修改数据

创建函数计算每位客户的风险因素,函数没有DETERMINISTIC(确定性)
输入同个client_id可能会返回不同值,这个客户后续可能会支付其他发票,所以风险因素随时可以改变
①选择READS SQL DATA
从获取风险因素过程复制变量、选择语句、计算风险因素的公式
②修改选择语句

执行后使用:

(结果为NULL,,暂时无解)
③解决出现空值:


把函数放在SQL文件,并放在源代码里
使用DROP FUNCTION IF EXISTS
![]()
11、OTHER CONVENTIONS——其他约定
函数:加fn前缀
存储过程:
①加proc、proc_前缀
②用驼峰式proGetRiskFactor(每个词首字母都大小写,除了第一个单词)
③直接getGetRiskFactor、get_risk_factor
DELIMITER使用$$或者//
以上约定根据已经在用的那种使用即可,无需强制使用那一种
(不要和老同事吵用哪种)
但如果从头推进一个项目,就可以根据自己的喜好约定
关键在于遵循已经存在的约定
————TBC
相关文章:
MySQL数据分析进阶(八)存储过程
※食用指南:文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记,笔记整理比较粗糙,主要目的自存为主,记录完整的学习过程。(图片超级多,慎看!) 【中字】SQL进阶教程 | 史上最易懂S…...
最深的根,
1498. 最深的根 题目 提交记录 讨论 题解 视频讲解 一个无环连通图可以被视作一个树。 树的高度取决于所选取的根节点。 现在,你要找到可以使得树的高度最大的根节点。 它被称为最深的根。 输入格式 第一行包含整数 NN,表示节点数量。 节点…...
【常见的设计模式】工厂模式
【设计模式专题之工厂方法模式】2.积木工厂 题目描述 小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。 输入描述 输入的第一行是一个整数 N(1 …...
postgres收缩工具两种工具的使用对比
postgres收缩工具安装和使用 第一章 需要使用插件处理膨胀的原因 Postgresql通过数据多版本实现MVCC,现象是删除数据并不会真正删除数据,而是修改标识,更新是通过删除+插入的方式进行,所以在频繁更新的OLTP系统,会造成数据膨胀。 PG数据库本身有处理膨胀问题的vacuum工…...
仿真入门——CST软件如何设置分布式计算的共享储存
在 CST Studio Suite 的分布式计算中,常有用户因为某台机器的网络问题丢失某个数据。这里介绍一种方法,可以在使用分布式计算或 MPI 计算时设置共享存储。在这种情况下,不涉及文件传输,所有文件操作都在共享文件的媒介上完成。 数…...
【JVM基础17】——实践-说一下JVM调优工具
目录 1- 引言:2- ⭐核心:2-1 命令工具jpsjstackjmapjstat 2-2 可视化工具jconsoleVisualVM 3- 小结:3-1 说一下 JVM 调优的工具 1- 引言: 命令工具 jps——进程状态信息jstack——查看Java进程内线程的堆栈信息jmap——查看堆转…...
【QT】Qt中Websocket的使用
一、WebSocket的定义 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,…...
【vue3】【elementPlus】【国际化】
1.如需从0-1开始,请参考 https://blog.csdn.net/Timeguys/article/details/140995569 2.使用 vue-i18n 模块: npm i vue-i18n3.在 src 目录下创建 locales 目录,里面创建文件:en.js、zh-cn.js、index.js 语言js文件:…...
用python实现求两个整数的最大公约数
def gcd(a, b): """计算最大公约数""" while b: a, b b, a % b return abs(a) 下面是对 gcd 函数的逐行解释: def gcd(a, b):"""计算最大公约数"""定义函数:这里定义了一个名为 gcd…...
Linux 内核源码分析---proc 文件系统
proc文件系统 进程数据文件系统(process data filesystem, procfs)装载在 /proc,缩写为 procFS。 proc 文件系统是一种虚拟文件系统,其信息不能从块设备读取。只有在读取文件内容时才动态生成相应的信息。使用proc文件系统&…...
视频号直播回放怎么下载?
一、如果是下载自己直播回放视频: 方法一:视频号助手 打开网址:视频号助手 登陆账号后。下面路径,先点击成回放, 后就可以在下面路径,下载全场回放 但是这种有个缺点,就是不能分段下载。这样…...
【第九节】python中xml解析和json编解码
目录 一、Python XML 解析 1.1 什么是XML 1.2 Python 对 XML 的解析方法 1.3 SAX解析xml 1.4 xml.dom解析xml 1.6 ElementTree解析XML 二、Python编解码json 2.1 什么是json 2.2 使用json 库 2.3 使用第三方库Demjson 一、Python XML 解析 1.1 什么是XML XML&#x…...
yolo v8部署到云服务器问题记录
环境安装 1、运行项目报错:no python application found, check your startup logs for errors 在云服务器pytorch版本安装错了,安装了GPU版本,需要安装CPU版本 # CPU only 使用下面这段代码避免出现第二个错误 pip install torch2.3.1 to…...
端口被占用,杀死进程的步骤
一、 查看所有进程占用的端口 在开始-运行-cmd,输入:netstat –ano可以查看所有进程 二、查看占用指定端口的程序 查看被那个端口占用,可以用该命令: 三、使用命令杀死进程 杀死进程,使用命令:...
接口入门(企业常见使用,一分钟搞定版)
目录 1、接口的定义 定义位置 接口内容 2、接口的使用 正常实现接口 接口当做函数参数 匿名实现接口 3、OPPO便签接口具体分析 总结一下: 1、接口的定义 定义位置 可以写在类中,但注意现在接口名字是 类名.接口名 可以单独写在一个文件 接口内…...
深入解析:Cookie 与 Session 的区别及应用场景
引言 在Web开发中,Cookie 和 Session 是两种常用的用户状态管理机制。虽然它们的目标都是在无状态的HTTP协议中维护用户的状态,但它们的工作原理和适用场景却有所不同。在本文中,我们将深入探讨 Cookie 和 Session 的区别,并通过…...
LLM金融文本分类文档说明
Python注意事项: 1,创建虚拟环境: conda create --prefixD:\software\Anaconda3\envs\finance_analysis python3.10.4 conda create -p D:/software/anaconda3/envs/finance_analysis python3.10.4 注释: D:\software\anaconda3\e…...
EI检索,2天录用,3天见刊!截稿在即,这本水刊你还不投吗?
点击关注:关注GZH【欧亚科睿学术】,GET完整版2023JCR分区列表! 🎉 🎉 🎉 🎉 恭喜!这本毕业水刊仅2天录用!3天见刊! 重要时间节点如下 2024-08-03 Sub…...
sql获取过去的小时数
TIMESTAMPDIFF(HOUR, create_time, NOW()) AS pastHours 是一条 SQL 语句的一部分,它使用 TIMESTAMPDIFF 函数来计算两个时间点之间的差异,并将结果标记为 pastHours。 让我们详细解析一下这条语句: TIMESTAMPDIFF 函数: 这个函数用于计算两…...
【Android Studio】彻底卸载
文章目录 卸载程序控制面板卸载安全软件卸载 重启计算机删除文件重启计算机 我们在Android开发时涉及重装时,如果卸载不干净,再次安装是不会正常运行项目的,接下来就让我教你如何删除干净吧。 卸载程序 控制面板卸载 control控制面板一>…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
