Mysql笔记-存储过程与存储函数

1. 存储过程(Stored Procedure)

1.1 概述

1.1.1 定义:

存储过程是一组预编译的 SQL 语句和控制流语句(如条件判断、循环)的集合,​无返回值​(但可通过 OUT/INOUT 参数或结果集返回数据)。它支持参数传递、事务控制、异常处理等高级特性,适合封装复杂的业务逻辑(如批量数据操作、多表关联查询)。(打包sql)

1.1.2 作用-(打包sql)

  • 1、简化操作,提高了sql语句的重用性,减少了开发程序员的压力
  • 2、减少操作过程中的失误,提高效率
  • 3、减少网络传输量(客户端不需要把所有的 SQL 语句通过网络发给服务器)
  • 4、减少了 SQL 语句暴露在网上的风险,也提高了数据查询的安全性

1.1.3 适合场景 --(其实现在也不常用了)

  1. ​复杂业务逻辑​:如订单处理(涉及库存扣减、支付记录、物流状态更新)。
  2. ​批量数据操作​:如定时任务(每日统计销售额并生成报表)。
    ​3. 事务控制​:确保多个 SQL 操作要么全部成功,要么全部回滚(START TRANSACTION + COMMIT/ROLLBACK)。
    ​4. 性能优化​:减少网络传输(一次调用执行多个语句),利用预编译提升执行效率。

1.2 创建及使用存储过程

1.2.1 创建语法:

DELIMITER 新的结束标记 如 $ ---此句非必须 
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[特性列表...]
BEGIN
存储过程体
END $ --如上方的DELIMITER是$ 这里也要是¥
  1. 特性列表(characteristics )​:可选,常见如 DETERMINISTIC(结果确定)、NO SQL(无 SQL 查询)、READS SQL DATA(读取 SQL 数据)等(用于优化器或安全策略)。-此处暂不展开
  2. BEGIN 和 END: 存储过程体中可以有多条 SQL 语句,如果仅仅一条SQL 语句,则可以省略 BEGIN 和 END。
  3. DELIMITER:因为MySQL默认的语句结束符号为分号‘;’。为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER改变存储过程的结束符。当使用DELIMITER命令时,应该避免使用反斜杠(‘\’)字符,因为反斜线是MySQL的转义字符。 “DELIMITER //”语句的作用是将MySQL的结束符设置为//,并以“END //”结束存储过程。存储过程定义完毕之后再使用“DELIMITER ;”恢复默认结束符。

1.2.2 参数-IN\OUT:

  • 1、没有参数(无参数无返回)
  • 2、仅仅带 IN 类型(有参数无返回)
  • 3、仅仅带 OUT 类型(无参数有返
    回)
  • 4、既带 IN 又带 OUT(有参数有返回)
  • 5、带 INOUT(有参数有返回)
  • IN :当前参数为输入参数,也就是表示入参;
  • 存储过程只是读取这个参数的值。如果没有定义参数种类, 默认就是 IN ,表示输入参数。
  • OUT :当前参数为输出参数,也就是表示出参;(执行完成之后,调用这个存储过程的客户端或者应用程序就可以读取这个参数返回的值了。)
  • INOUT :当前参数既可以为输入参数,也可以为输出参数。
    注意:IN、OUT、INOUT 都可以在一个存储过程中带多个。

1.2.3 调用存储过程

一、语法格式

CALL 存储过程名(实参列表)

二、调用不参数的存储过程

1、调用in模式的参数:
CALL sp1('值');
2、调用out模式的参数:
SET @name;
CALL sp1(@name);
SELECT @name;
3、调用inout模式的参数:
SET @name=;
CALL sp1(@name);
SELECT @name;

1.2.4 示例

举例1(标识符使用):创建存储过程select_all_data(),查看 emps 表的所有数据

DELIMITER $
CREATE PROCEDURE select_all_data()
BEGIN
SELECT * FROM emps;
END $
DELIMITER ;

举例2(参数使用):创建存储过程show_someone_salary2(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名,用OUT参数empsalary输出员工薪资。

DELIMITER //
CREATE PROCEDURE show_someone_salary2(IN empname VARCHAR(20),OUT empsalary DOUBLE)
BEGIN
SELECT salary INTO empsalary FROM emps WHERE ename = empname;
END //
DELIMITER ;

2. 存储函数(Stored Function)

存储函数是一段返回单个值的特殊存储过程,​必须有且仅有一个返回值​(通过 RETURNS 子句声明类型)。它的参数只能是输入参数(IN 类型),且返回值通常用于 SQL 表达式(如 SELECT、WHERE 子句)。

2.1 概述

2.1.1 定义

存储函数是一段返回单个值的特殊存储过程,​必须有且仅有一个返回值​(通过 RETURNS 子句声明类型)。它的参数只能是输入参数(IN 类型),且返回值通常用于 SQL 表达式(如 SELECT、WHERE 子句)。
举例:常见的函数:LENGTH、SUBSTR、CONCAT等

2.1.2 作用

  1. 封装计算逻辑,返回单个值
  2. 简化 SQL 查询,避免重复代码
  3. 替代视图或触发器中的复杂逻辑
  4. 提高执行效率:存储函数在数据库中预编译,调用时直接执行编译后的代码,减少了 SQL 解析和传输的开销,尤其适用于高频调用的轻量级计算

2.1.3 适合场景–(这个现在也不常用)

​1. 计算密集型操作​:如日期格式化(FORMAT_DATE())、数值计算(CALC_TAX())。
​2. 数据校验​:如验证手机号格式(返回 VALID 或 INVALID)。
​3. 简化 SQL 查询​:在 SELECT 语句中调用函数,避免重复编写复杂表达式(如 SELECT GET_USERNAME(user_id))。

2.2 创建及使用存储过程

2.2.1 创建语法:

CREATE FUNCTION 函数名(参数名 参数类型,...)
RETURNS 返回值类型
[characteristics ...]
BEGIN
函数体 #函数体中肯定有 RETURN 语句
END

1、参数列表:FUNCTION中总是默认为IN参数。(指定参数为IN、OUT或INOUT只对存储过程是合法的,)
2、RETURNS type 语句表示函数返回数据的类型;(必须有
3、characteristic 同存储过程相同。
4、函数体也可以用BEGIN…END来表示SQL代码的开始和结束。如果函数体只有一条语句,也可以省略。同存储过程相似。

2.2.2 调用存储过程

在MySQL中,存储函数的使用方法与MySQL内部函数的使用方法是一样的。换言之,用户自己定义的存储函数与MySQL内部函数是一个性质的。区别在于,存储函数是 用户自己定义 的,而内部函数是MySQL.的 开发者定义 的

SELECT 函数名(实参列表)

2.2.3 示例

存储函数创建示例

#示例1
DELIMITER //
CREATE FUNCTION email_by_name()
RETURNS VARCHAR(25)
DETERMINISTIC
CONTAINS SQLBEGIN
RETURN (SELECT email FROM employees WHERE last_name = 'Abel');
END //
DELIMITER ;##示例2
DELIMITER $$
CREATE FUNCTION CalculateTax(orderAmount DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC  -- 声明结果确定(相同输入返回相同结果)
READS SQL DATA  -- 声明仅读取数据(无写操作)
BEGINRETURN orderAmount * 0.1;  -- 返回计算结果
END
$$
DELIMITER ;

存储函数调用示例

SELECT count_by_id(@dept_id);--调用无参数
SELECT email_by_name();--调用有参数

3. 存储过程 与 存储函数 管理

存储过程 与 存储函数 的查看、修改,删除

3.1 查看

  1. 查看创建信息–SHOW CREATE
SHOW CREATE {PROCEDURE | FUNCTION} 存储过程名或函数名
--示例
SHOW CREATE FUNCTION test_db.CountProc;
  1. 查看状态信息-SHOW STATUS
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
SHOW PROCEDURE STATUS LIKE 'SELECT%' \G
  1. 查看属性信息-information_schema.Routines表
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='存储过程或函数的名' [AND ROUTINE_TYPE = {'PROCEDURE|FUNCTION'}];
-示例
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='count_by_id' AND ROUTINE_TYPE = 'FUNCTION' \G

3.2 修改

修改已创建的存储过程或存储函数主要有两种方式:​使用 ALTER 语句修改对象属性​ 或 ​使用 CREATE OR REPLACE 语句覆盖原定义​(推荐用于逻辑修改)
一、使用 ALTER PROCEDURE(FUNCTION) 修改属性(有限修改)
ALTER PROCEDURE 用于修改存储过程的元数据属性​(如注释、参数模式、安全模式等),但无法修改存储过程的逻辑代码块​(即 BEGIN…END 内的 SQL 语句)。

-- 原存储过程定义(假设已存在)
DELIMITER $$
CREATE PROCEDURE GetUserCount()
BEGINSELECT COUNT(*) FROM users;
END
$$
DELIMITER ;-- 修改注释和安全模式
ALTER PROCEDURE GetUserCount
COMMENT '获取系统总用户数(仅读取数据)'
READS SQL DATA;

二、 使用 CREATE OR REPLACE PROCEDURE 覆盖原定义(推荐逻辑修改)
若需修改存储过程的逻辑代码块​(如调整 SQL 语句、参数列表或流程控制),必须通过 CREATE OR REPLACE PROCEDURE 重新定义。该语句会删除原存储过程并创建新的同名过程,因此需确保新定义与原过程类型一致(均为 PROCEDURE)。

CREATE [OR REPLACE] PROCEDURE procedure_name([参数列表])
[特性列表]
BEGIN-- 新的 SQL 逻辑代码块
END;

三、 完全删除后重新创建(备用方案)
若 CREATE OR REPLACE 无法满足需求(如参数类型变更导致无法覆盖),可先删除原存储过程,再重新创建。

3.3 删除

删除存储过程和函数,可以使用DROP语句,其语法结构如下:

DROP {PROCEDURE | FUNCTION} [IF EXISTS] 存储过程或函数的名
--示例
DROP PROCEDURE CountProc;
DROP FUNCTION CountProc;

4. 存储过程 与 存储函数 比较

维度存储过程存储函数
返回值可无返回值,支持通过 OUT/INOUT 参数传递多个值,或返回多结果集必须有且仅返回单一值(标量或表)
参数类型支持 IN / OUT / INOUT 三类参数仅支持 IN 类型参数
调用方式通过 CALL 过程名() 独立调用直接嵌入 SQL 语句(如 SELECT 函数名()
事务处理允许使用 COMMIT / ROLLBACK 控制事务禁止事务操作
数据修改权限允许执行 INSERT / UPDATE / DELETE 等 DML 操作禁止修改数据库状态(只读)
临时表可创建并使用临时表仅支持使用表变量(不能创建临时表)
适用场景复杂业务逻辑(批量处理、事务性操作),如订单支付、数据迁移轻量级计算(数值转换、动态字段生成),如税率计算
语法要求使用 BEGIN...END 包裹复杂逻辑必须包含 RETURN 语句定义返回值

阿里开发规范
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
存储过程主要缺点如下:
1、可移植性差。存储过程不能跨数据库移植,比如在 MySQL、Oracle 和 SQL Server 里编写的存储过程,在换成其他数据库时都需要重新编写。
2、调试困难。只有少数 DBMS 支持存储过程的调试。对于复杂的存储过程来说,开发和维护都不容易。虽然也有一些第三方工具可以对存储过程进行调试,但要收费。
3、存储过程的版本管理很困难。比如数据表索引发生变化了,可能会导致存储过程失效。我们在开发软件的时候往往需要进行版本管理,但是存储过程本身没有版本控制,版本迭代更新的时候很麻烦。
4、它不适合高并发的场景。高并发的场景需要减少数据库的压力,有时数据库会采用分库分表的方式,而且对可扩展性要求很高,在这种情况下,存储过程会变得难以维护, 增加数据库的压力 ,显然就
不适用了。

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

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

相关文章

[论文阅读] 人工智能 + 软件工程 | LLM协作新突破:用多智能体强化学习实现高效协同——解析MAGRPO算法

LLM协作新突破:用多智能体强化学习实现高效协同——解析MAGRPO算法 论文:LLM Collaboration With Multi-Agent Reinforcement LearningarXiv:2508.04652 (cross-list from cs.AI) LLM Collaboration With Multi-Agent Reinforcement Learning Shuo Liu, …

使用OAK相机实现智能物料检测与ABB机械臂抓取

大家好!今天我们很高兴能与大家分享来自OAK的国外用户——Vention 的这段精彩视频,展示了他们的AI操作系统在现实中的应用——在演示中,进行实时的自动物料拣选。 OAK相机实时自动AI物料拣选视频中明显可以看到我们的OAK-D Pro PoE 3D边缘AI相…

html5和vue区别

HTML5 是网页开发的核心标准,而 Vue 是构建用户界面的JavaScript框架,两者在功能定位和开发模式上有显著差异: 核心定位 HTML5是 HTML标准 的第五次重大更新(2014年发布),主要提供网页结构定义、多媒体嵌入…

【前端八股文面试题】【JavaScript篇3】DOM常⻅的操作有哪些?

文章目录🧭 一、查询/获取元素 (Selecting Elements)✏️ 二、修改元素内容与属性 (Modifying Content & Attributes)🧬 三、创建与插入元素 (Creating & Inserting Elements)🗑️ 四、删除与替换元素 (Removing & Replacing)&am…

内存杀手机器:TensorFlow Lite + Spring Boot移动端模型服务深度优化方案

内存杀手机器:TensorFlow Lite Spring Boot移动端模型服务深度优化方案一、系统架构设计1.1 端云协同架构1.2 组件职责矩阵二、TensorFlow Lite深度优化2.1 模型量化策略2.2 模型裁剪技术2.3 模型分片加载三、Spring Boot内存优化3.1 零拷贝内存管理3.2 堆外内存模…

安全生产基础知识(一)

本文档围绕安全生产基础知识展开: 一、安全用电相关知识 用电安全要点 禁止用湿手触摸灯头、开关、插头插座及用电器具。发现有人触电,切勿用手拉扯,应立即拉开电源开关或用干燥木棍、竹竿挑开电线。电器通电后出现冒烟、烧焦味或着火时&…

Elasticsearch 搜索模板(Search Templates)把“可配置查询”装进 Mustache

1. 什么是 Search Template?能解决什么问题? 搜索模板是存储在 ES 集群里的 Mustache 模板(lang: mustache)。你把一份标准 _search 请求体写成模板,变量交给 params,每次调用只需传参即可: 搜索…

cocos Uncaught TypeError: Cannot read properties of null (reading ‘SetActive‘)

报错:Uncaught TypeError: Cannot read properties of null (reading SetActive) at b2RigidBody2D.setActive (rigid-body.ts:231:21) at b2RigidBody2D.onEnable (rigid-body.ts:78:14) at RigidBody2D.onEnable (rigid-body-2d.ts:551:24) at OneOffInvoker.invo…

Docker用户组介绍以及管理策略

在Docker环境中,用户组(尤其是默认的docker组)是管理用户与Docker守护进程交互权限的核心机制。以下从概念介绍和具体管理操作两方面详细说明:一、Docker用户组的核心概念 Docker守护进程(dockerd)默认通过…

【PyTorch】单目标检测项目部署

【PyTorch】单目标检测项目 两种部署情况:部署在 PyTorch 数据集上,以及部署在本地存储的单个映像上。 目录 定义数据集 搭建模型 部署模型 定义数据集 详细参照前文【PyTorch】单目标检测项目 import torchvision import os import pandas as pd i…

Baumer高防护相机如何通过YoloV8深度学习模型实现火星陨石坑的检测识别(C#代码UI界面版)

《------往期经典推荐------》 AI应用软件开发实战专栏【链接】 序号 项目名称 项目名称 1 1.工业相机 + YOLOv8 实现人物检测识别:(C#代码,UI界面版) 2.工业相机 + YOLOv8 实现PCB的缺陷检测:(C#代码,UI界面版) 2 3.工业相机 + YOLOv8 实现动物分类识别:(C#代码,U…

UniApp Vue3 TypeScript项目中使用xgplayer播放m3u8视频的显示问题

问题背景 在UniApp Vue3 TypeScript项目中使用xgplayer播放m3u8视频时&#xff0c;遇到了一个棘手的问题&#xff1a;视频画面下移&#xff0c;只能听到声音&#xff0c;全屏后才能正常显示。经过排查&#xff0c;发现是<video>元素在DOM渲染时被异常定位&#xff0c;导…

服务器硬件电路设计之 I2C 问答(三):I2C 总线上可以接多少个设备?如何保证数据的准确性?

在服务器硬件电路设计中&#xff0c;I2C 总线作为常用的串行通信协议&#xff0c;其设备连接数量和数据准确性至关重要。​I2C 总线上可连接的设备数量并非无限制。从理论上讲&#xff0c;标准 I2C 设备采用 7 位地址&#xff0c;除去保留地址&#xff0c;最多可连接 112 个设备…

用LaTeX优化FPGA开发:结合符号计算与Vivado工具链

用 LaTeX 优化 FPGA 开发&#xff1a;结合符号计算与 Vivado 工具链&#xff08;一&#xff09; 系列文章目录 第一章&#xff1a;深入了解 LaTeX&#xff1a;科技文档排版的利器 第二章&#xff1a;LaTeX 下载安装保姆级教程 第三章&#xff1a;LaTeX 创建工程并生成完整文档…

人工智能系列(6)如何开发有监督神经网络系统?

一. 开发有监督神经网络系统的步骤1. 数据收集训练数据通常由输入–输出成对组成&#xff0c;根据任务需求可能涵盖不同情境&#xff08;如白天或夜晚的车辆识别&#xff09;&#xff0c;其类型可以是数值、图像、音频等多种形式&#xff1b;数据规模越大、越多样&#xff0c;模…

CSS 选择器进阶:用更聪明的方式定位元素

在前端开发中&#xff0c;CSS 选择器是我们与 DOM 对话的语言。虽然 class 和 id 是我们最熟悉的工具&#xff0c;但真正高效、优雅的样式代码&#xff0c;往往来自于对现代 CSS 选择器的深入理解与巧妙运用。本文将带你跳出基础语法&#xff0c;探索那些能显著提升开发效率和代…

常用排序方法

一、排序的概念及引用1、排序的概念排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&…

接口返回504 Gateway Time-out 错误,这意味着请求在网关或代理服务器等待上游服务器响应时超时。以下是可能的原因和排查建议:

问题分析1.后端处理耗时过长是某个方法执行时间过长&#xff0c;超过了网关的超时设置&#xff08;通常是几十秒&#xff09;可能涉及大量数据查询或复杂计算2.数据库查询性能问题查询的数据量过大缺少必要的数据库索引SQL语句执行效率低下排查建议1.检查服务端日志查看应用日志…

DBAPI 实现不同角色控制查看表的不同列

DBAPI 实现不同角色控制查看表的不同列 场景说明 在数据库管理系统中&#xff0c;对表进行列级别的权限控制是一项关键的安全措施&#xff0c;特别是在处理敏感数据或需要遵守特定数据访问控制策略的情况下。合理的列权限控制不仅能保护敏感信息&#xff0c;还能帮助组织满足合…

二维图像处理(完整版)

目录 1.变换矩阵 2.在矩阵的基础上添加各种变换形式 3.开始变换 4.计算变换矩阵参数 新算子 二、阈值分割 新算子 三、blob分析案例 1.焊点 2.石头 3.木材 4.车牌 5.骰子 新算子 四、傅里叶变换频域分析 问题一 五、滤波处理 1.均值滤波 2.中值滤波 3.高斯…