mysql 存储过程和自定义函数 详解

首先创建存储过程或者自定义函数时,都要使用use database 切换到目标数据库,因为存储过程和自定义函数都是属于某个数据库的。

存储过程是一种预编译的 SQL 代码集合,封装在数据库对象中。以下是一些常见的存储过程的关键字:

存储过程

1. 存储过程的定义

  • CREATE PROCEDURE: 用于创建一个新的存储过程。

    CREATE PROCEDURE procedure_name (parameter_list)
    BEGIN-- 存储过程体
    END;
  • DROP PROCEDURE: 用于删除已存在的存储过程。

    DROP PROCEDURE procedure_name;

2. 参数定义

  • IN: 表示输入参数。

  • OUT: 表示输出参数。

  • INOUT: 表示既可以输入又可以输出的参数。

    CREATE PROCEDURE my_procedure(IN param1 INT, OUT param2 INT)
    BEGIN-- 存储过程体
    END;

3. 变量声明与操作

  • DECLARE: 定义局部变量、条件和游标。

    DECLARE var1 INT DEFAULT 0;
    DECLARE var2 VARCHAR(50);
  • SET: 用于给变量赋值。

    SET var1 = 10;

4. 控制流程

  • BEGIN/END: 标记存储过程块的开始和结束。

    BEGIN-- 存储过程体
    END;
  • IF 条件判断

    IF 语句用于简单的条件分支。

    语法格式
    IF condition THENSQL逻辑
    ELSEIF condition THENSQL逻辑
    ELSESQL逻辑
    END IF;
    案例

    根据用户 ID 返回不同的信息。

    DELIMITER //
    CREATE PROCEDURE CheckUser(IN userId VARCHAR(32))
    BEGINDECLARE userName VARCHAR(32);IF userId = 'APP-2016-00494878' THENSELECT username INTO userName FROM users WHERE userid = userId;SELECT userName;ELSEIF userId = 'APP-2016-7777777' THENSELECT userage INTO userName FROM users WHERE userid = userId;SELECT userName;ELSESELECT userId;END IF;
    END //
    DELIMITER ;

    调用存储过程:

    CALL CheckUser('APP-2016-00494878');
  • CASE: 用于多条件判断。

  • 语法格式
    CASEWHEN condition1 THENSQL逻辑WHEN condition2 THENSQL逻辑ELSESQL逻辑
    END CASE;
  • 根据用户角色返回不同的权限级别。

  • DELIMITER //
    CREATE PROCEDURE GetUserRole(IN userId INT)
    BEGINDECLARE userRole VARCHAR(20);SELECT role INTO userRole FROM users WHERE id = userId;CASE userRoleWHEN 'admin' THENSELECT 'Administrator';WHEN 'user' THENSELECT 'Standard User';ELSESELECT 'Guest';END CASE;
    END //
    DELIMITER ;

    调用存储过程:

    CALL GetUserRole(1);
  • LOOP/WHILE/REPEAT: 实现循环操作。

    LOOP_LABEL: LOOP-- 循环体IF condition THENLEAVE LOOP_LABEL;END IF;
    END LOOP;

 WHILE 循环

WHILE 循环在条件为真时执行循环体中的 SQL 语句。

语法格式
WHILE 条件 DOSQL逻辑
END WHILE;
案例

计算从 1 累加到 n 的值,n 为传入的参数值。

DELIMITER //
CREATE PROCEDURE CalculateSum(IN n INT)
BEGINDECLARE total INT DEFAULT 0;WHILE n > 0 DOSET total = total + n;SET n = n - 1;END WHILE;SELECT total;
END //
DELIMITER ;

调用存储过程:

CALL CalculateSum(100);

 

REPEAT 循环

REPEAT 循环至少执行一次循环体中的 SQL 语句,直到条件为真时退出循环。

语法格式
REPEATSQL逻辑
UNTIL 条件
END REPEAT;
案例

计算从 1 累加到 n 的值,n 为传入的参数值。

DELIMITER //
CREATE PROCEDURE CalculateSumRepeat(IN n INT)
BEGINDECLARE total INT DEFAULT 0;REPEATSET total = total + n;SET n = n - 1;UNTIL n <= 0END REPEAT;SELECT total;
END //
DELIMITER ;

调用存储过程:

CALL CalculateSumRepeat(100);

LOOP 循环

LOOP 循环是无条件循环,通常与 LEAVE 语句结合使用来退出循环。

语法格式
[loop_label:] LOOPSQL逻辑
END LOOP [loop_label];
案例

计算从 1 累加到 n 的值,n 为传入的参数值。

DELIMITER //
CREATE PROCEDURE CalculateSumLoop(IN n INT)
BEGINDECLARE total INT DEFAULT 0;sum_loop: LOOPIF n <= 0 THENLEAVE sum_loop;END IF;SET total = total + n;SET n = n - 1;END LOOP sum_loop;SELECT total;
END //
DELIMITER ;

调用存储过程:

CALL CalculateSumLoop(100);

 

5. 条件处理

  • DECLARE HANDLER: 定义异常处理程序。

    DECLARE CONTINUE HANDLER FOR SQL_ERROR_CODE error_code
    BEGIN-- 异常处理语句
    END;

6. 游标操作

  • DECLARE CURSOR: 声明游标。

    DECLARE cursor_name CURSOR FOR SELECT column1, column2 FROM table WHERE condition;
  • OPEN CURSOR: 打开游标。

    OPEN cursor_name;
  • FETCH CURSOR: 读取游标数据。

    FETCH cursor_name INTO var1, var2;
  • CLOSE CURSOR: 关闭游标。

    CLOSE cursor_name;

7. 调试与优化

  • SET: 调整优化器参数。

    SET optimizer_switch = 'index_merge=on';
  • SHOW VARIABLES: 查看系统变量。

    SHOW VARIABLES LIKE 'optimizer_switch';

8.案例 

以下是一个包含事务处理的存储过程示例:

DELIMITER //CREATE PROCEDURE transfer_funds(IN from_account INT, IN to_account INT, IN amount DECIMAL(10,2))
BEGINSTART TRANSACTION;IF amount > 0 THEN-- 从源账户扣除金额UPDATE accounts SET balance = balance - amount WHERE id = from_account;-- 向目标账户增加金额UPDATE accounts SET balance = balance + amount WHERE id = to_account;-- 提交事务COMMIT;ELSE-- 回滚事务ROLLBACK;END IF;
END //DELIMITER ;

这个存储过程通过事务确保资金转账操作的原子性。

9.补充知识:游标

注意事项

  • 游标只能在存储过程和函数中使用

  • 游标是只读的,不能用于修改数据,但可以通过 SELECT 查询结果集。

  • 需要显式地打开和关闭游标,以确保资源的正确释放。

通过使用游标,可以对查询结果集进行逐行处理,这对于需要对每行数据执行复杂操作的场景非常有用

DELIMITER //
CREATE PROCEDURE ProcessOrders()
BEGINDECLARE done INT DEFAULT 0;DECLARE orderId INT;DECLARE orderStatus VARCHAR(20);-- 声明一个名为 cur 的游标。-- 该游标基于查询 SELECT id, status FROM orders,用于存储查询结果集。-- 可以通过游标逐行访问和操作 orders 表中的每一行数据。DECLARE cur CURSOR FOR SELECT id, status FROM orders;-- 定义一个异常处理程序,当游标遍历完所有行(触发 NOT FOUND 异常)时,将变量 done 设置为 1。DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;OPEN cur; -- 打开游标order_loop: LOOPFETCH cur INTO orderId, orderStatus; -- 从游标中提取数据IF done THENLEAVE order_loop; -- 如果没有更多数据,退出循环END IF;-- 在这里处理每一行数据UPDATE orders SET status = 'processed' WHERE id = orderId;END LOOP order_loop;CLOSE cur; -- 关闭游标
END //
DELIMITER ;

在这个存储过程中,当游标遍历完所有行时,FETCH cur INTO orderId, orderStatus 会触发 NOT FOUND 异常。此时,CONTINUE HANDLERdone 设置为 1,退出循环。

通过这种方式,可以优雅地处理游标遍历完成的情况,确保程序不会因异常而中断。

10.查询当前数据库有哪些存储过程 

SELECT SPECIFIC_NAME AS '存储过程名', ROUTINE_SCHEMA AS '数据库名', CREATED AS '创建时间', LAST_ALTERED AS '最后修改时间'
FROM information_schema.ROUTINES
WHERE ROUTINE_TYPE = 'PROCEDURE'AND ROUTINE_SCHEMA = 'test_mybatis';

自定义函数

1. 定义自定义函数

  • CREATE FUNCTION: 用于创建一个新的自定义函数。

    CREATE FUNCTION function_name (parameter_list)
    RETURNS return_type
    BEGIN-- 函数体
    END;
    • function_name: 函数名称。

    • parameter_list: 参数列表,参数可以是 IN 类型。

    • RETURNS: 指定函数返回值的类型。

2. 参数定义

  • IN: 定义输入参数。MySQL 的自定义函数只支持 IN 类型的参数。

    CREATE FUNCTION add_numbers(IN a INT, IN b INT)
    RETURNS INT
    BEGINRETURN a + b;
    END;

3. 函数体

  • BEGIN/END: 标记函数体的开始和结束。

    BEGIN-- 函数逻辑
    END;

4. 返回值

  • RETURN: 用于返回函数的计算结果。

    RETURN value;

5. 属性

  • DETERMINISTICNOT DETERMINISTIC: 标记函数是否是确定性的。

    • 确定性函数:对于相同的输入参数总是返回相同的结果。

    • 非确定性函数:对于相同的输入参数可能返回不同的结果。

    CREATE FUNCTION function_name (parameter_list)
    RETURNS return_type DETERMINISTIC
    BEGIN-- 函数逻辑
    END;

6. 修改或删除函数

  • ALTER FUNCTION: 修改已存在的自定义函数。

  • DROP FUNCTION: 删除已存在的自定义函数。

    DROP FUNCTION function_name;

7. 调用函数

  • 可以直接在 SQL 语句中调用自定义函数。

    SELECT add_numbers(5, 10);

存储过程和自定义函数区别 

特性存储过程自定义函数
定义是一组预编译的 SQL 语句和流程控制语句的集合,可以包含多个 SQL 语句和复杂逻辑。是一个用户定义的函数,用于封装特定的功能逻辑,返回一个值。
返回值可以没有返回值,也可以通过 OUT 参数返回多个值。必须返回一个值,返回值类型在创建函数时指定。
参数类型支持 INOUT 和 INOUT 类型的参数。只支持 IN 类型的参数。
调用方式使用 CALL 语句调用,不能在 SELECT 中直接调用。可以在 SQL 语句中直接调用,如 SELECTWHEREORDER BY 等。
事务处理可以包含事务操作,控制事务的提交和回滚。不支持事务操作。
代码重用适合封装复杂的业务逻辑,便于维护和代码重用。适合封装简单的逻辑,如计算、转换或条件判断,便于在多个地方重用。
性能存储过程在服务器端执行,与应用程序交互次数少,性能较高。自定义函数在查询中调用时,可能会导致性能问题,需要谨慎使用。
适用场景适用于执行复杂操作的场景,如批量更新数据、执行多个 SQL 语句或返回结果集。适用于需要返回单个值的场景,如计算、转换或简单的逻辑判断。

总结

  • 存储过程:适合执行复杂的操作,可以返回多个值或结果集,适用于批量更新数据、执行多个 SQL 语句或返回结果集等场景。

  • 自定义函数:适合返回单个值的简单逻辑,可以直接在 SQL 语句中调用,适用于计算、转换或条件判断等场景。

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

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

相关文章

基于STM32的智能鱼缸水质净化系统设计

&#x1f91e;&#x1f91e;大家好&#xff0c;这里是5132单片机毕设设计项目分享&#xff0c;今天给大家分享的是智能鱼缸水质净化系统。 目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 1、设计要求…

如何打造一个更友好的网站结构?

在SEO优化中&#xff0c;网站的结构往往被忽略&#xff0c;但它其实是决定谷歌爬虫抓取效率的关键因素之一。一个清晰、逻辑合理的网站结构&#xff0c;不仅能让用户更方便地找到他们需要的信息&#xff0c;还能提升搜索引擎的抓取效率 理想的网站结构应该像一棵树&#xff0c;…

尝试在Excel里调用硅基流动上的免费大语言模型

我个人觉得通过api而不是直接浏览器客户端聊天调用大语言模型是使用人工智能大模型的一个相对进阶的阶段。 于是就尝试了一下。我用的是老师木 袁进辉博士新创的硅基流动云上的免费的大模型。——虽然自己获赠了不少免费token&#xff0c;但测试阶段用不上。 具体步骤如下&am…

mongodb 使用内存过大分析

os 分析 内存使用 ps aux|head -1;ps aux|grep -v PID|sort -rn -k 4|head -10swap 使用 for i in $(ls /proc | grep "^[0-9]" | awk $0>100); do awk /Swap:/{aa$2}END{print "$i",a/1024"M"} /proc/$i/smaps;done| sort -k2nr | headmo…

整理:熟悉MySQL的使用和运行原理,掌握索引、事务、锁等机制。了解存储引擎、读写分离、分库分表。

系列博客目录 文章目录 系列博客目录1.MySQL的运行原理2.MySQL的使用步骤 1&#xff1a;创建数据库步骤 2&#xff1a;创建表2.1 创建 users 表2.2 创建 products 表 步骤 3&#xff1a;插入数据3.1 向 users 表插入数据3.2 向 products 表插入数据 步骤 4&#xff1a;查询数据…

“公路养护新利器!公路 AI 智慧巡检系统

家人们&#xff0c;咱日常开车出行&#xff0c;最烦的就是遇到路面坑洼、道路破损的情况&#xff0c;不仅颠簸难受&#xff0c;还存在安全隐患。其实&#xff0c;这些问题都得靠公路养护人员及时发现并处理。但以往的公路巡检工作可不容易&#xff0c;现在好了&#xff0c;有了…

mysql mvcc 锁 关系

多版本并发控制&#xff08;MVCC&#xff09;是一种用于数据库并发控制的机制&#xff0c;它可以在保证数据一致性的同时&#xff0c;提高数据库的并发性能。下面结合 MVCC 机制&#xff0c;详细阐述常见的四种事务隔离级别&#xff08;读未提交、读已提交、可重复读、串行化&a…

2502vim,vim文本对象中文文档

介绍 文本块用户(textobj-user)是一个可帮助你毫不费力地创建自己的文本对象的Vim插件. 因为有许多陷阱需要处理,很难创建文本对象.此插件隐藏了此类细节,并提供了声明式定义文本对象的方法. 你可用正则式来定义简单的文本对象,或使用函数来定义复杂的文本对象.如… 文本对…

AUTOSAR面试题集锦(1)

最基础概念 目录 最基础概念 什么是AUTOSAR?AUTOSAR到底做了什么? AUTOSAR的结构是什么样的?分为哪几层? MCAL开发 什么是MCAL? 使用过EB吗?怎样使用EB配置MCAL工程? autosar4.3.1和4.4.0有什么区别? 什么是复杂驱动? 为什么使用多核?AUTOSAR提供了几种多核…

【算法】动态规划专题⑧ —— 分组背包问题 python

目录 前置知识进入正题实战演练总结 前置知识 【算法】动态规划专题⑤ —— 0-1背包问题 滚动数组优化 python 进入正题 分组背包问题的详细解析 1. 问题定义 在 分组背包问题 中&#xff0c;物品被划分为若干组&#xff0c;每组内的物品 互斥&#xff08;只能选择其中一个或…

LLM:DeepSeek 系列(二)

原文链接 3、DeepSeek-V2 DeepSeek-V2 发布于 2024 年 5 月&#xff0c;为多领域专家&#xff08;MoE&#xff09;语言模型&#xff0c;包含总共 2360 亿个参数&#xff0c;其中每个词元激活 210 亿个参数&#xff0c;并支持 12.8 万个词元的上下文长度。DeepSeek-V2 采用包括…

AtCoder Beginner Contest 391(A~E题题解)

A - Lucky Direction 思路&#xff1a;纯模拟的一个水题 #include <bits/stdc.h> using namespace std; #define int long long string s; signed main() { cin>>s;for(int i0;i<s.size();i){char cs[i];if(cN){cout<<"S";}else if(c…

redis中的hash结构

hash类型也叫散列&#xff0c;其中value是一个无序字典&#xff0c;不用像string类型中的value用jason结构去存储&#xff0c;他的value可以将对象中的每个字段独立存储&#xff0c;而且有个好处&#xff0c;方便修改value值 类似于这样 hash类型的常见命令&#xff1a;

USB子系统学习(四)使用libusb读取鼠标数据

文章目录 1、声明2、HID协议2.1、描述符2.2、鼠标数据格式 3、应用程序4、编译应用程序5、测试 1、声明 本文是在学习韦东山《驱动大全》USB子系统时&#xff0c;为梳理知识点和自己回看而记录&#xff0c;全部内容高度复制粘贴。 韦老师的《驱动大全》&#xff1a;商品详情 …

02.08 多路文件IO

思维导图1&#xff1a; 思维导图2&#xff1a; 高效处理多路文件IO&#xff1a;select、poll和epoll模型详解 在现代网络编程中&#xff0c;高效地监视多个文件描述符的IO状态&#xff08;如可读、可写、异常&#xff09;是至关重要的。本文将详细介绍三种常用的多路文件IO模…

opentelemetry-collector 配置elasticsearch

一、修改otelcol-config.yaml receivers:otlp:protocols:grpc:endpoint: 0.0.0.0:4317http:endpoint: 0.0.0.0:4318 exporters:debug:verbosity: detailedotlp/jaeger: # Jaeger supports OTLP directlyendpoint: 192.168.31.161:4317tls:insecure: trueotlphttp/prometheus: …

基于联合概率密度与深度优化的反潜航空深弹命中概率模型研究摘要

前言:项目题材来自数学建模2024年的D题,文章内容为笔者和队友原创,提供一个思路。 摘要 随着现代军事技术的发展,深水炸弹在特定场景下的反潜作战效能日益凸显,如何最大化的发挥深弹威力也成为重要研究课题。本文针对评估深弹投掷落点对命中潜艇概率的影响进行分析,综合利…

fps动作系统2:手臂动画

文章目录 角色蓝图pawn自动控制玩家 动画蓝图事件图表动画图表状态机时长 随机序列播放器混合空间播放器权重速度 角色蓝图 pawn 自动控制玩家 设置玩家控制器控制此pawn。 动画蓝图 事件图表 更新角色的相关数值 动画图表 设置角色相关动画以及切换规则 状态机 状态…

使用 ElementUI 和 Spring 实现稳定可靠的文件上传和下载功能

前端(ElementUI) 1. 文件上传 使用 el-upload 组件配置上传接口处理上传成功和失败<template><div><el-uploadclass="upload-demo"action="http://your-server-url/upload":on-success="handleSuccess":on-error="handle…

Docker安装pypiserver私服

Docker安装pypiserver私服 1 简介 Python开源包管理工具有pypiserver、devpi和Nexus等&#xff0c;pypiserver安装部署比较简单&#xff0c;性能也不错。 搭建pypiserver私服&#xff0c;可以自己构建镜像&#xff0c;也可以使用官网的docker镜像。 # Github地址 https://g…