当前位置: 首页 > news >正文

MySQL中的存储过程详解(上篇)

使用语言 MySQL

使用工具 Navicat Premium 16

代码能力快速提升小方法,看完代码自己敲一遍,十分有用

  • 拖动表名到查询文件中就可以直接把名字拉进来
  • 中括号,就代表可写可不写 

目录

1.认识存储过程

1.1 存储过程的作用 

1.2 存储过程简介

1.3 MySQL存储过程的优缺点

1.3.1 优点

1.3.2 缺点

2.创建和调用存储过程

2.1 创建存储过程 

2.1.1 常用特性

2.1.2 声明默认语句分隔符 

2.1.3 参数的3种类型 

2.1.4 过程体的标识 

2.2 调用存储过程

2.2.1 无参示例

2.2.2 带参示例 

2.3 存储过程中的变量

2.3.1 一行定义多个变量 

2.3.2 变量赋值

2.3.3  用户自定义变量和系统变量

2.3.4 示例 

2.4 使用navicat创建存储过程 

2.4.1 创建存储过程

2.4.2 执行存储过程 

2.4.3 示例 

2.5 设置用户权限

2.5.1 基本概念 

2.5.2 definer特性 

2.5.3 sql security的作用 

2.5.4 示例


 

1.认识存储过程

1.1 存储过程的作用 

在数据库开发过程中,存在一个功能需要多个SQL语句组合在一起实现并被多次调用的情况。在数据库中定义存储过程,可以提升代码的复用率,提高开发效率。 

1.2 存储过程简介

存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数的值(如果该存储过程带有参数)来执行。存储过程是数据库中的一个重要对象。MySQL从5.0版本开始支持存储过程,时数据库引擎更加灵活强大。
存储过程就是数据库SQL语言层面上的代码封装与重用。 (存储过程就跟Java中的方法差不多)

1.3 MySQL存储过程的优缺点

1.3.1 优点

  • 存储过程就是数据库SQL语言层面上的代码封装与重用。
  • 提高性能: 存储过程在数据库服务器上编译和存储,可以减少网络流量,提高性能。一旦创建,它们在多次调用中可以重复使用,而不需要每次都重新编译。
  • 减少网络流量: 因为存储过程在数据库服务器上运行,所以只需要传输参数和结果,而不是传输整个 SQL 查询,这可以减少网络流量,提高效率。
  • 减少重复代码: 存储过程可以将一组 SQL 语句封装在一个单独的单元中,使得可以重复使用相同的逻辑,减少了重复编写相同代码的需求,提高了代码的可维护性。
  • 增强安全性: 通过存储过程,可以控制用户对数据库的访问权限,只需授予执行存储过程的权限,而不需要直接操作底层表。
  • 支持事务处理: 存储过程可以包含事务处理逻辑,允许开发者在单个单元内执行多个 SQL 语句,并且可以确保这些操作要么全部成功,要么全部失败。

1.3.2 缺点

  • 学习成本高: 编写存储过程需要熟悉特定的存储过程语言(如 MySQL 的存储过程语言),这可能需要额外的学习成本。
  • 数据库依赖性: 存储过程是与特定数据库管理系统相关的,如果需要切换到另一个数据库管理系统,可能需要重新编写存储过程。
  • 难以调试: 存储过程通常比在应用程序中直接执行 SQL 更难调试。在某些情况下,错误可能会在运行时才被发现,并且难以跟踪。
  • 维护困难: 存储过程中的逻辑可能会分散在数据库中,这可能使得对代码的维护和修改更加困难。
  • 性能优化困难: 在某些情况下,存储过程可能会导致性能问题,特别是当存储过程中包含复杂的逻辑或查询时,需要进行额外的性能优化。 

存储过程在提高性能、减少网络流量、减少重复代码和增强安全性等方面具有优势,但在学习成本高、数据库依赖性强、调试困难和维护困难等方面存在一些挑战。因此,在选择是否使用存储过程时,需要根据具体的应用场景和需求权衡其优缺点。 

2.创建和调用存储过程

2.1 创建存储过程 

存储过程简称过程(Procedure)。在MySQL中,使用 create procedure语句创建存储过程的语法格式如下: 

create procedure 过程名([过程参数[,.....]])
[特性]
存储过程体

过程名一般以pro_开头;

其中,特性为可选项,用于调整存储过程的行为。下面对一些常用的特性进行说明:

2.1.1 常用特性

  • LANGUAGE SQL:存储默认语言,默认值为SQL
  • {CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}:存储过程要做哪类工作,默认值为CONTAINS SQL。
  • SQL SECURITY{DEFINER|INVOKER}:用来指定存储过程的执行权限,默认值为DEFINER。
  • DEFINER:使用创建者的权限执行。
  • INVOKER:使用执行者的权限执行。
  • COMMENT'string':存储过程的注释信息。 

2.1.2 声明默认语句分隔符 

在MySQL中,默认使用";"作为分隔符,使用DELIMITER关键字可以改变分隔符。在创建存储过程,首先声明分隔符。将分隔符设置为"$$"或"//"的语法格式如下:

  • DELIMITER $$ 或者 DELIMITER //

如果没有声明分隔符,编译器就会把存储过程当成SQL语句处理,这样编译过程就会报错。由于我使用的版本是Navicat Premium 16,已经优化了这个问题,所以可以不用声明分隔符。注意,最后要把分隔符还原。语法格式如下:

  • delimiter ; 

2.1.3 参数的3种类型 

在MySQL中,存储过程的参数包括3种类型。

  • in:输入参数。该参数的值必须在调用存储过程时指定,在存储过程中可以使用该参数,但它不能被返回。
  • out:输出参数。该参数可以在存储过程中发生改变并可以返回。
  • inout:输入输出参数。在参数的值在调用存储过程时指定,在存储过程中可以被改变和返回。定义参数的语法如下:

 [in | out | inout] 参数名 数据类型

如果需要定义多个参数,需要使用','进行分隔。 

2.1.4 过程体的标识 

在定义存储过程的过程体时,需要标识开始和结束。语法格式如下:

  • begin ... end 分隔符

end后面必须使用delimiter语句中设置的分隔符为结束。 

2.2 调用存储过程

创建存储过程之后,如何进行调用呢?在MySQL中使用call关键字调用存储过程,语法非常简单。语法格式如下:

  • call 存储过程名(参数列表);

存储过程调用类似于Java中的方法调用。括号中根据存储过程的定义包含相应的参数。下面看具体示例:

2.2.1 无参示例

 

运行结果 

 这样会打印出三个结果,分别时存储过程中对应的三个语句,相比执行单独的SQL语句,存储过程最大的优势是将一系列SQL语句集合起来,允许使用参数,使开发过程变得更加灵活。

2.2.2 带参示例 

 

运行结果 

 

这里使用select into将查询获得的数据放入输出参数。调用存储过程时,必须在过程名后面的括号中包含与定义过程相匹配数目的参数,如@a。这里把@a成为用户变量。加两个@@号的就是全局变量(系统变量)。调用过程结束,就可以通过select查看输出结果。 

2.3 存储过程中的变量

类似Java等其他编程语言,定义存储过程时可以使用使用变量。声明变量的语法格式如下:

  • declare 变量名[,变量名....] 数据类型 [default 值];

例如,声明交易时间变量trade_time,并设置默认值为2020-07-10 

  • declare trade_time date default '2020-07-10';

2.3.1 一行定义多个变量 

  • DECLARE var1 INT, var2 VARCHAR(255), var3 DECIMAL(10,2);-- 这里的一行中定义了三个变量:var1 是一个整数类型的变量,var2 是一个长度为 255 的字符串类型的变量,var3 是一个十进制数类型的变量,精度为 10,小数点后保留 2 位。 

也可以分为多行来一个一个定义,意思都是一样的 ;

2.3.2 变量赋值

在定义存储过程时,所有局部变量的声明一定要放在存储过程体的开始,否则会提示语法错误;
声明变量后,可以给变量赋值。
语法格式如下:

  • set 变量名=表达式值[,变量名=表达式...];

例如,设置变量total的值为100:

  • set total=100; 

2.3.3  用户自定义变量和系统变量

在MySQL中,变量包含用户自定义变量和系统变量两种。这里重点讲用户自定义变量。 

MySQL用户自定义变量包括局部变量和会话变量。 

  • 局部变量一般用于SQL的语句块中,如存储过程中的begin和end语句块,其作用域仅限于于定义该变量的语句块内,生命周期也仅限于该存储过程的调用期间。在存储过程执行到end时,局部变量就会被释放。
  • 会话变量也被称为用户变量,是服务器为每个客户端连接维护的变量,与MySQL客户端时绑定的。用户变量可以暂存值,并传递给同一连接中其他SQL语句使用。在MySQL客户端连接退出时,用户变量就会被释放。用户变量创建时一般"@"开头,形式为"@变量名"。 

2.3.4 示例 

  • 使用select into语句可以一次给多个变量赋值,用逗号隔开然后有对应的查询列即可;
  • 使用into打印数据不能有多个数据返回,就是一次只能存一个值,不能同时返回多个值

运行结果 

 

定义用户变量 

 

运行结果 

 

2.4 使用navicat创建存储过程 

存储过程为多条SQL语句的集合,在实际项目开发过程中具有广泛的应用。如果能更便捷地编写和调试存储过程,将大大提升开发效率。navicat提供了良好的开发环境,比MySQL命令行操作更加便捷。 

2.4.1 创建存储过程

 

右击数据库下的"函数"节点,在弹出的快捷菜单中执行"新建函数"命令选中以上这个即可。 

  • 在程序模版中完成存储过程的编写。因为navicat默认指定用户目前创建的是存储过程,所以在navicat中编写存储过程时,不需要再使用delimiter声明新的分隔符。 
  • 在默认情况下,系统在新建函数时会自动打开函数向导。该向导通过可视化界面输入存储过程名称、参数列表完成存储过程模版的创建。可以按照以下步骤关闭函数向导:"工具"-"选项"-"常规"-“显示函数向导”复选框;

2.4.2 执行存储过程 

  • 存储过程编写完毕后,保存之后,存储过程将自动保存在当前所在数据库的函数节点下。
  • 保存后,单击运行按钮调用存储过程。根据存储过程的定义,有两个输入参数,在打开的"输入参数"对话框中输入设定的用户参数值点击确定按钮,执行存储过程并输出结果。 

2.4.3 示例 

输入参数

 

打印结果 

 

navicat提供了可视化的方式创建和执行存储过程,使存储过程的开发和管理变得更加轻松。 

2.5 设置用户权限

2.5.1 基本概念 

  • 创建的存储模版自动增加DEFINER赋值语句,他作为一个可选项,用于规定对存储过程访问的安全控制。在MySQL中,通过DEFINER和SQL SECURITY特性控制存储过程的执行权限的语法格式如下:

create
[definer={user|current_user}] # 定义definer
procedure 存储过程名
[SQL SECURITY{DEFINER | INVOKER}]| ...] # 特性
begin
......
end

  • definer默认为当前用户。如果创建者有super权限,也可以指定definer值为其他用户。能否访问该存储过程取决于该用户是否有调用该存储过程的权限(INVOKER权限),以及是否有存储过程中SQL语句的select权限。

2.5.2 definer特性 

  • 在MySQL中,DEFINER 是用于定义存储过程、函数、视图等对象的创建者(或拥有者)的关键字。这在 SQL 安全性方面具有重要意义,特别是在多用户环境中。
  • 当你创建一个存储过程、函数或视图时,MySQL 默认会将当前执行该创建语句的用户作为该对象的创建者,这意味着只有该用户拥有对该对象的执行权限。然而,在某些情况下,你可能希望将对象的执行权限授予其他用户或角色,而不是创建者本身。
  • 这时,你可以使用 DEFINER 关键字指定一个特定的用户或角色作为对象的创建者。这样,无论哪个用户执行该对象,实际上都是以 DEFINER 指定的用户的权限来执行。这有助于在数据库中实现更细粒度的权限控制和安全性。 

例如,创建一个存储过程并指定 DEFINER:

CREATE DEFINER = 'user'@'host' PROCEDURE procedure_name()
BEGIN
    -- 存储过程内容
END; 

例子分析

  • 在这个例子中,存储过程 procedure_name 的创建者被指定为 user 用户,而不是当前执行该语句的用户。
  • 需要注意的是,使用 DEFINER 关键字可能存在一些安全风险,特别是当指定的用户拥有高权限时。因此,在使用时需要谨慎考虑,并确保适当的安全措施已经实施,以防止潜在的安全漏洞。 

2.5.3 sql security的作用 

sql security特性可以指定为definer或invoker,用以指定是在定义者(definer)或调用者(invoker)上下文中执行。若省略sql security特性,则默认值是definer上下文。 

definer和invoder决定存储过程不同的执行方式。(查询账号权限可以去mysql数据库中的user表查看(Y代表可以执行,N代表不能执行)) 

2.5.4 示例

definer属性值 

对于存储过程p1,任何对p1具有执行权限的用户都可以使用call语句调用。但需要注意的是,当执行存储过程的时候,'admin'@'localhost用户必须同时拥有p1的执行权限和对表t1的update权限;否则,存储过程将执行失败如上所示。 

invoder属性值

这将在 MySQL 中创建一个名为 p2 的存储过程,它将以调用者的权限执行。请确保用户调用该存储过程时具有足够的权限来更新表 t1,否则就会出现异常。 

相关文章:

MySQL中的存储过程详解(上篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法,看完代码自己敲一遍,十分有用 拖动表名到查询文件中就可以直接把名字拉进来中括号,就代表可写可不写 目录 1.认识存储过程 1.1 存储过程的作用 1.2 存储过程简介…...

面试官:说一说CyclicBarrier的妙用!我:这个没用过...

写在开头 面试官:同学,AQS的原理知道吗? 我:学过一点,抽象队列同步器,Java中很多同步工具都是基于它的… 面试官:好的,那其中CyclicBarrier学过吗?讲一讲它的妙用吧 我&…...

MySQL高可用搭建方案MHA

MHA架构介绍 MHA是Master High Availability的缩写,它是目前MySQL高可用方面的一个相对成熟的解决方案,其核心是使用perl语言编写的一组脚本,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中&am…...

【vue】用vite创建vue项目

前置要求 要有Node.js 1. 用vite创建vue项目 在cmd中,进入一个文件夹 在文件资源管理器上面的文件目录中,输入cmd,回车在cmd中通过cd命令进入对应文件夹 创建项目 npm create vitelatest # 创建项目创建项目过程中的一些选项 Ok to pro…...

内网渗透-内网环境下的横向移动总结

内网环境下的横向移动总结 文章目录 内网环境下的横向移动总结前言横向移动威胁 威胁密码安全 威胁主机安全 威胁信息安全横向移动威胁的特点 利用psexec 利用psexec.exe工具msf中的psexec 利用windows服务 sc命令 1.与靶机建立ipc连接2.拷贝exe到主机系统上3.在靶机上创建一个…...

Linux命令学习—linux 的常用命令

1.1、改变目录 cd 目录的表达方法: /根目录 .当前目录 .. 上一级目录 ~家目录 #cd / 进入到系统根目录 #cd . 进入当前目录 #cd .. 进入当前目录的父目录,返回上层目录 #cd /tmp 进入指定目录/tmp #cd ~ 进入当前用户的家目录 #cd …...

【Git教程】(十)版本库之间的依赖 —— 项目与子模块之间的依赖、与子树之间的依赖 ~

Git教程 版本库之间的依赖 1️⃣ 与子模块之间的依赖2️⃣ 与子树之间的依赖🌾 总结 在 Git 中,版本库是发行单位,代表的是一个版本,而分支或标签则只能被创建在版本库这个整体中。如果一个项目中包含了若干个子项目,…...

最新版IntelliJ IDEA 2024.1安装和配置教程 详细图文解说版安装教程

IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版 文章目录 IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版前言 第一步: IntelliJ IDEA 2024.1安装教程第 0 步&…...

JVM常用参数一

jvm启动参数 JVM(Java虚拟机)的启动参数是在启动JVM时可以设置的一些命令行参数。这些参数用于指定JVM的运行环境、内存分配、垃圾回收器以及其他选项。以下是一些常见的JVM启动参数: -Xms:设置JVM的初始堆大小。 -Xmx&#xff1…...

分布式锁-redission可重入锁原理

5.3 分布式锁-redission可重入锁原理 在Lock锁中,他是借助于底层的一个voaltile的一个state变量来记录重入的状态的,比如当前没有人持有这把锁,那么state0,假如有人持有这把锁,那么state1,如果持有这把锁的…...

Android Gradle开发与应用 (八) :Kotlin DSL

1. 前言 本文介绍了Gradle Kotlin DSL相关的一些知识点 2. DSL是什么 DSL是为特定领域设计的专门的语言,也就是设计了一门语言,然后解决某个特定的领域的特定问题。 2.1 举例说明 以下的这些都可以称之为DSL 正则表达式 :用于文本处理的特定语言SQ…...

phpstorm 快捷键

PHPstorm最常用的快捷键,提高开发效率 - 知乎 (zhihu.com) 四年精华PHP技术文章整理合集——PHP框架篇 (qq.com) 四年精华PHP技术文合集——微服务架构篇 (qq.com) Vue3 打印票据 预览的库:vue3打印解决方案:Vue-Plugin-HiPrint - 掘金 (j…...

浦大喜奔APP8.0智能升级,发力数字金融深化五大金融篇章服务

1. 浦大喜奔立足科技赋能持续迭代升级,筑牢用户体验护城河 浦发信用卡中心坚持数字科技与客户体验双轮驱动,以科技赋能发展,优化整体系统性能,全方位支撑浦大喜奔 APP提高线上客户服务能力与体验,积极服务民生消费&a…...

自然语言处理、大语言模型相关名词整理

自然语言处理相关名词整理 零样本学习(zero-shot learning)词嵌入(Embedding)为什么 Embedding 搜索比基于词频搜索效果好? Word2VecTransformer检索增强生成(RAG)幻觉采样温度Top-kTop-p奖励模…...

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑,这些问题可能会影响我们的开发效率和代码质量,因此我们需要不断总结和学习,以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结,以提高大家的开发质量。本系列文章…...

太好玩了,我用 Python 做了一个 ChatGPT 机器人

毫无疑问,ChatGPT 已经是当下编程圈最火的话题之一,它不仅能够回答各类问题,甚至还能执行代码! 或者是变成一只猫 因为它实在是太好玩,我使用Python将ChatGPT改造,可以实现在命令行或者Python代码中调用。…...

STM32存储左右互搏 SDIO总线读写SD/MicroSD/TF卡

STM32存储左右互搏 SDIO总线读写SD/MicroSD/TF卡 SD/MicroSD/TF卡是基于FLASH的一种常见非易失存储单元,由接口协议电路和FLASH构成。市面上由不同尺寸和不同容量的卡,手机领域用的TF卡实际就是MicroSD卡,尺寸比SD卡小,而电路和协…...

累积分布函数图(CDF)的介绍、matlab的CDF图绘制方法(附源代码)

在对比如下两个误差的时候,怎么直观地分辨出来谁的误差更低一点?: 通过这种误差时序图往往不容易看出来。 但是如果使用CDF图像,以误差绝对值作为横轴,以横轴所示误差对应的累积概率为纵轴,绘制曲线图&am…...

代码随想录算法训练营第四十一天|343.整数拆分、96不同的二叉搜索树

文档链接:https://programmercarl.com/ LeetCode343.整数拆分 题目链接:https://leetcode.cn/problems/integer-break/ 思路: j * (i - j) 是单纯的把整数拆分为两个数相乘,而j * dp[i - j]是拆分成两个以及两个以上的个数相乘…...

全量知识系统 程序详细设计之 统一资产模型(QA-SmartChat)

Q1. 下面我们聊聊整个全知系统的设计 的矩阵和函数,矩阵表示的是“活物”,分别 类似 一个基因的活性、一个实体的辨识度和某种特征的可区分度。 函数的可微、可积和可导性 则表示 运动的控制方式 在全知系统设计中,矩阵和函数是两个核心的组…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

SpringCloudGateway 自定义局部过滤器

场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...