MySQL学习(存储过程)

文章目录

  • 基本概念
  • 变量定义
  • 参数传递
    • in: 传入参数
    • out:传出参数
    • inout:传入传出参数
  • 流程控制
    • if-else
    • case: 类似Switch
    • 循环
  • 游标(cursor)
  • 异常处理
  • 存储过程练习
  • 存储函数

基本概念

  • 存储过程就是一组SQL语句集,实现一些比较复杂的逻辑功能,存储过程在数据库中创建,在其他程序中调用。
  • 存储过程就是数据库SQL语言层面的代码封装,可以重复调用。
  • 特性
  1. 有输入输出参数,参数可以有默认值,可以声明变量。
  2. 有一些控制语句,比如if、while等。通过编写存储过程,可以完成一些复杂的SQL逻辑操作。
  3. 模块化、封装、代码复用。
  4. 执行速度快,因为存储过程在创建时就已经编译和优化过,执行效率高。
  • 语法:
delimiter 自定义结束符号
create procedure 存储过程名( in|out 参数名 数据类型, ...)
beginSQL语句
end 自定义结束符号
delimiter ; -> 恢复默认结束符号';'
  • 创建存储过程
delimiter $$create procedure p1()
beginselect a.ename, a.empno from emp a;
end $$
delimiter ;
  • 删除存储过程
drop procedure if exists p1;
  • 调用存储过程
call p1();

变量定义

/*
局部变量: 只在begin...end中有效在begin...end中定义,使用declare关键字语法:declare var_name 类型 [default value];
用户变量:当前会话(连接)有效不需要提前声明语法:@var_name
系统变量:分为全局变量和会话变量全局变量:在MySQL启动时服务器自动初始化为默认值,默认值可以通过my.ini文件更改语法:@@global.var_name会话变量:每次建立新的连接的时候,由MySQL将全局变量的值复制给会话变量语法:@@session.var_name区别:修改全局变量会影响MySQL服务器,而会话变量只会影响当前会话(连接)系统变量有的可以利用语句更改,有的是只读的
*/
  • 局部变量
    delimiter $$create procedure p2()begindeclare var1 varchar(20) default 'abc'; -- 定义/声明变量declare var2 varchar(20);set var1 = 'def'; -- 赋值方式1select a.ename into var2 from emp a where a.empno = 7369; -- 赋值方式2select var1, var2;    -- 输出变量end $$delimiter ;call p2();
  • 用户变量
    delimiter $$create procedure p3()beginset @var1 = 'abc'; -- 定义/声明变量select @var1;    -- 输出变量end $$delimiter ;call p3();select @var1;   -- 也可以查询到变量
  • 系统变量
        -- 全局变量show global variables;  -- 查看全局变量select @@global.auto_increment_offset; -- 查看某全局变量-- 修改某全局变量的值set @@global.auto_increment_offset = 2;set global auto_increment_offset = 2;-- 会话变量show session variables;  -- 查看会话变量select @@session.auto_increment_offset; -- 查看某会话变量-- 修改某会话变量的值set @@session.auto_increment_offset = 2;set session auto_increment_offset = 2;

参数传递

in: 传入参数

  • 传入员工编号,查找员工姓名
        delimiter $$create procedure p4(in parameter_empno int)beginselect a.ename, a.empno from emp a where a.empno = parameter_empno;end $$delimiter ;call p4(7900);
  • 传入部门名称和工资,查找该部门中工资高于指定工资的员工
        delimiter $$create procedure p5(in parameter_dname varchar(20), in parameter_salary double)beginselect a.ename, b.dname, a.salfrom emp a, dept bwhere b.dname = parameter_dname and a.sal > parameter_salary and a.deptno = b.deptno;end $$delimiter ;call p5('researach', 1000);

out:传出参数

  • 传入员工编号,传出该员工的名字
        delimiter $$create procedure p6(in parameter_empno int, out parameter_ename varchar(20))beginselect a.ename into parameter_ename from emp a where a.empno = parameter_empno;end $$delimiter ;call p6(7902, @var1);select @var1;   -- 输出传出参数
  • 传入员工编号,传出该员工的名字和工资
        delimiter $$create procedure p7(in parameter_empno int, out parameter_ename varchar(20), out paraneter_sal double)beginselect a.ename, a.sal into parameter_ename, paraneter_sal from emp a where a.empno = parameter_empno;end $$delimiter ;call p7(7902, @var1, @var2);select @var1, @var2;   -- 输出传出参数

inout:传入传出参数

从外部传入参数,在存储过程中改变它,最后将结果返回

  • 传入一个数字,传出他的10倍
        delimiter $$create procedure p8(inout parameter_num int)beginset parameter_num = parameter_num * 10;end $$delimiter ;set @var1 = 5;call p8(@var1);select @var1;   -- 输出
  • 传入员工姓名和工资,将员工的名字拼接部门编号,工资乘以12
        delimiter $$create procedure p9(inout parameter_ename varchar(20), inout parameter_sal double)beginselect concat(a.deptno, '-', parameter_ename) into parameter_ename from emp a where a.ename = parameter_ename;select parameter_sal * 12 into parameter_sal;end $$delimiter ;set @var1 = 'jack';set @var2 = 8000;call p9(@var1, @var2);select @var1, @var2;   -- 输出

流程控制

if-else

  • 成绩等级
        /*输入学生成绩,判断成绩等级score < 60: 不及格score >= 60 and score < 80: 及格score >= 80 and score < 90: 良好score >= 90 and score <= 100: 优秀score > 100: 成绩错误*/delimiter $$create procedure p10(in parameter_score int, out parameter_grade varchar(20))beginif parameter_score < 60then set parameter_grade = '不及格';elseif parameter_score >= 60 and parameter_score < 80then set parameter_grade = '及格';elseif parameter_score >= 80 and parameter_score < 90then set parameter_grade = '良好';elseif parameter_score >= 90 and parameter_score <= 100then set parameter_grade = '优秀';elseset parameter_grade = '成绩错误';end if;end $$delimiter ;call p10(85, @var1);select @var1;   -- 输出
  • 传入员工姓名,判断该员工的工资等级
        delimiter $$create procedure p11(in parameter_ename varchar(20), out parater_sal_level int)begindeclare var_sal, var_losal, var_hisal double;select a.sal into var_sal from emp a where a.ename = parameter_ename;select b.losal, b.hisal into var_losal, var_hisal from salgrade b where b.grade = 1;if var_sal >= var_losal and var_sal <= var_hisalthen set parater_sal_level = 1;end if;select c.losal, c.hisal into var_losal, var_hisal from salgrade c where c.grade = 2;if var_sal > var_losal and var_sal <= var_hisalthen set parater_sal_level = 2;end if;select d.losal, d.hisal into var_losal, var_hisal from salgrade d where d.grade = 3;if var_sal > var_losal and var_sal <= var_hisalthen set parater_sal_level = 3;end if;select e.losal, e.hisal into var_losal, var_hisal from salgrade e where e.grade = 4;if var_sal > var_losal and var_sal <= var_hisalthen set parater_sal_level = 4;end if;select f.losal, f.hisal into var_losal, var_hisal from salgrade f where f.grade = 5;if var_sal > var_losal and var_sal <= var_hisalthen set parater_sal_level = 5;end if;end $$delimiter ;call p11('jack', @var1);select @var1;   -- 输出

case: 类似Switch

        delimiter $$create procedure p12(in pay_type int)begincase pay_typewhen 1 then select '现金支付';when 2 then select '银行卡支付';when 3 then select '支付宝支付';when 4 then select '微信支付';else select '其他支付方式';end case;end $$delimiter ;call p12(3);   -- 输出

循环

  • 分类:while, loop, repeat
  • 控制:leave类似于break,iterate类似于continue
  • 新建一个表
        create table if not exists user(uid int,username varchar(20),password varchar(20));
  • 向表中添加指定条数的数据
  1. while循环
                -- whiletruncate user;  -- 清空表delimiter $$create procedure p13(in parameter_InsertCount int)begindeclare i int default 1;while i <= parameter_InsertCount doinsert into user(uid, username, password) values(i, concat('user', i), concat('pwd', i));set i = i + 1;end while;end $$delimiter ;call p13(5);-- while + leavetruncate user;  -- 清空表delimiter $$create procedure p14(in parameter_InsertCount int)begindeclare i int default 1;label: while 1 doinsert into user(uid, username, password) values(i, concat('user', i), concat('pwd', i));if i >= parameter_InsertCountthen leave label;end if;set i = i + 1;end while label;end $$delimiter ;call p14(5);
  1. reapeat循环
                truncate user;  -- 清空表delimiter $$create procedure p15(in parameter_InsertCount int)begindeclare i int default 1;label: repeatinsert into user(uid, username, password) values(i, concat('user', i), concat('pwd', i));set i = i + 1;until i > parameter_InsertCountend repeat label;end $$delimiter ;call p15(5);
  1. loop循环
            truncate user;  -- 清空表delimiter $$create procedure p16(in parameter_InsertCount int)begindeclare i int default 1;label: loopinsert into user(uid, username, password) values(i, concat('user', i), concat('pwd', i));set i = i + 1;if i > parameter_InsertCountthen leave label;end if;end loop label;end $$delimiter ;call p16(5);

游标(cursor)

  • cursor是用来储存查询结果集的数据类型,在存储过程中使用游标可以对结果集中的数据进行循环操作,包括声明、open、fetch和close
  • 语法
/*
语法:-- 声明游标:declare cursor_name cursor for select_statement;-- 打开游标:open cursor_name;-- 获取游标数据:fetch cursor_name into variable [,variable] 。。。;-- 关闭游标:close cursor_name;
*/
  • 需求:输入部门名称,查询该部门员工的编号、姓名和工资,将查询结果添加游标,然后逐行输出
	drop procedure if exists p17;   -- 删除存储过程delimiter $$create procedure p17(in parameter_dname varchar(20))begindeclare var_empno int;declare var_ename varchar(20);declare var_sal double;-- 声明游标declare my_cursor cursor forselect a.empno, a.ename, a.salfrom emp a, dept bwhere a.deptno = b.deptno and b.dname = parameter_dname;-- 打开游标open my_cursor;-- 获取数据label: loop		-- 有正确结果,但是会报错(not found)fetch my_cursor into var_empno, var_ename, var_sal;select var_empno, var_ename, var_sal;end loop label;-- 关闭游标close my_cursor;end $$delimiter ;call p17('sales');

异常处理

在程序中,如果发生错误,则程序会停止执行。为了防止这种情况的发生,可以使用异常处理机制

  • 语法
    /*语法:-- 声明异常处理:declare handler_type handlerfor condition_value [,condition_value] ...statement;-- 异常处理类型(handler_type):-- continue:继续执行-- exit:退出执行-- undo:撤销事务-- 异常处理条件(condition_value):-- mysql错误代码-- condition_name:异常名称-- sqlwarning:警告-- not found:未找到-- sqlexception:异常*/
  • 以上个例子为例,使用异常处理loop循环解决报错问题
    – 当遇到not found异常时将标记值flag赋值0,在loop循环中当flag为1时正常获取游标数据,为0时关闭循环并继续执行(continue)后面代码。
        delimiter $$create procedure p18(in parameter_dname varchar(20))begindeclare var_empno int;declare var_ename varchar(20);declare var_sal double;-- 定义标记值declare flag int default 1;-- 声明游标declare my_cursor cursor forselect a.empno, a.ename, a.salfrom emp a, dept bwhere a.deptno = b.deptno and b.dname = parameter_dname;-- 定义句柄declare continue handler for not found set flag = 0;-- 打开游标open my_cursor;-- 获取数据label: loop   -- 正确fetch my_cursor into var_empno, var_ename, var_sal;if flag = 1 thenselect var_empno, var_ename, var_sal;elseleave label;end if;end loop label;-- 关闭游标close my_cursor;end $$delimiter ;call p18('sales');

存储过程练习

  • 需求:提前一个月创建该月的所有表(每天一个,表名格式:table_user_2019_07_31)
    create database if not exists procedure_practice;use procedure_practice;drop procedure if exists proc_test;delimiter $$create procedure proc_test()begindeclare next_year int;  -- 下一个月的年份declare next_month int; -- 下一个月的月份declare next_month_day int; -- 下一个月的最后一天declare next_month_str varchar(2); -- 下一个月的月份字符串declare next_month_day_str varchar(2); -- 下一个月的日期字符串-- 每天的表名declare table_name_str varchar(50);declare t_index int default 1;-- 获取下一个月的年份set next_year = year(date_add(now(), interval 1 month));-- 获取下一个月的月份set next_month = month(date_add(now(), interval 1 month));-- 获取下一个月的最后一天set next_month_day = dayofmonth(last_day(date_add(now(), interval 1 month)));if next_month < 10 thenset next_month_str = concat('0', next_month);elseset next_month_str = concat('', next_month);end if;while t_index <= next_month_day doif t_index < 10 thenset next_month_day_str = concat('0', t_index);elseset next_month_day_str = concat('', t_index);end if;-- 拼接表的日期部分名称set table_name_str = concat(next_year, '_', next_month_str, '_', next_month_day_str);-- 拼接表名set table_name_str = concat('table_user_', table_name_str);-- 拼接创建表的sql语句set @create_table_sql = concat('create table if not exists ', table_name_str, '(uid int, uname varchar(50), information varchar(50)) collate=utf8mb4_general_ci engine=innodb');-- from 后面不能使用局部变量prepare create_table_stmt from @create_table_sql;   -- 根据存储在变量 @create_table_sql 中的SQL语句创建一个名为 create_table_stmt 的预编译语句。execute create_table_stmt;  -- 执行创建表的操作deallocate prepare create_table_stmt;   -- 取消准备之前创建的预编译语句,释放相关资源。-- 更新t_indexset t_index = t_index + 1;end while;end $$delimiter ;call proc_test();

存储函数

  • 格式
/*格式:create function 函数名(参数列表) returns 返回值类型begin函数体end;
*/
  • 创建存储函数(无参数)
        drop function if exists my_f1;delimiter $$create function my_f1() returns int READS SQL DATAbegindeclare num int default 0;select count(*) into num from emp;return num;end $$delimiter ;select my_f1(); -- 调用存储函数
  • 创建存储函数(有参数)
        drop function if exists my_f2;delimiter $$create function my_f2(id int) returns varchar(20) READS SQL DATAbegindeclare name varchar(20);select a.ename into name from emp a where a.empno = id;return name;end $$delimiter ;select my_f2(7369); -- 调用存储函数

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

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

相关文章

GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions

GIS OGC之WMTS地图服务&#xff0c;通过Capabilities XML描述文档&#xff0c;获取matrixIds&#xff0c;origin&#xff0c;计算resolutions 需求&#xff1a;如何根据WMTS服务的Capabilities描述文档得到&#xff0c;openlayers调用wmts服务时的matrixIds&#xff0c;origin…

Qwen 2.5:阿里巴巴集团的新一代大型语言模型

Qwen 2.5&#xff1a;阿里巴巴集团的新一代大型语言模型 摘要&#xff1a; 在人工智能领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展日新月异&#xff0c;它们在自然语言处理&#xff08;NLP&#xff09;和多模态任务中扮演着越来越重要的角色。阿里巴巴集…

探索RESTful风格的网络请求:构建高效、可维护的API接口【后端 20】

探索RESTful风格的网络请求&#xff1a;构建高效、可维护的API接口 在当今的软件开发领域&#xff0c;RESTful&#xff08;Representational State Transfer&#xff09;风格的网络请求已经成为构建Web服务和API接口的标配。RESTful风格以其简洁、无状态、可缓存以及分层系统等…

[数据集][目标检测]俯拍航拍森林火灾检测数据集VOC+YOLO格式6116张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6116 标注数量(xml文件个数)&#xff1a;6116 标注数量(txt文件个数)&#xff1a;6116 标注…

神经网络通俗理解学习笔记(0) numpy、matplotlib

Numpy numpynumpy 基本介绍Ndarray对象及其创建Numpy数组的基础索引numpy数组的合并与拆分&#xff08;重要&#xff09;numpy数组的矩阵运算Numpy数组的统计运算numpy中的arg运算numpy中的神奇索引和比较 Matplotlib numpy numpy 基本介绍 numpy 大多数机器学习库都用了这个…

视频监控平台是如何运作的?EasyCVR视频汇聚平台的高效策略与实践

随着科技的飞速发展&#xff0c;视频监控平台在社会安全、企业管理、智慧城市构建等领域发挥着越来越重要的作用。一个高效的视频监控平台&#xff0c;不仅依赖于先进的硬件设备&#xff0c;更离不开强大的视频处理技术作为支撑。这些平台集成了多种先进的视频技术&#xff0c;…

Python 如何封装工具类方法,以及使用md5加密

第一步&#xff1a;封装使用方法 在utils目录中&#xff0c;编写我的md5加密的方法&#xff0c;如下&#xff1a; import re import hashlib from os import path from typing import Callable from flask import current_app# 这里封装的是工具类的方法def basename(filenam…

Redis实现发布/订阅功能(实战篇)

前言 博主在学习 Redis 实现发布订阅功能的时候&#xff0c;踩了太多的坑。 不是讲解不详细&#xff0c;看的一知半解&#xff1b;就是代码有问题&#xff0c;实际压根跑不起来&#xff01; 于是博主萌生了自己写一个最新版且全程无错的博客供各位参考。希望各位不要把我才过…

【Python篇】深度探索NumPy(下篇):从科学计算到机器学习的高效实战技巧

文章目录 Python NumPy学习指南前言第六部分&#xff1a;NumPy在科学计算中的应用1. 数值积分使用梯形规则进行数值积分使用Simpson规则进行数值积分 2. 求解微分方程通过Euler方法求解一阶常微分方程使用scipy.integrate.solve_ivp求解常微分方程 3. 随机过程模拟模拟布朗运动…

Llama 3.1 Omni:颠覆性的文本与语音双输出模型

你可能听说过不少关于语言模型的进展,但如果告诉你,有一种模型不仅能生成文本,还能同时生成语音,你会不会觉得特别酷?今天咱们就来聊聊一个相当前沿的项目——Llama 3.1 Omni模型。这个模型打破了传统的文字生成边界,直接让文本和语音同时输出,实现了真正的"多模态…

网络爬虫到底难在哪里?

如果你是自己做爬虫脚本开发&#xff0c;那确实难&#xff0c;因为你需要掌握Python、HTML、JS、xpath、database等技术&#xff0c;而且还要处理反爬、动态网页、逆向等情况&#xff0c;不然压根不知道怎么去写代码&#xff0c;这些技术和经验储备起码得要个三五年。 比如这几…

基于milvus数据库的RAG-Demo

1.上传文本并将文本向量化 import os from django.conf import settings from langchain.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter, CharacterTextSplitter from langchain.vectorstores import Chroma from l…

C++掉血迷宫

目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 #include <iostream> #include <string> #include <cstring> using namespace std; enum RBYG {R 1,B 2,Y 4,G 7, }; struct heal {int ix…

Linux服务器本地部署Joplin Server并实现手机电脑多端同步文档

文章目录 前言1. 安装Docker2. 自建Joplin服务器3. 搭建Joplin Sever4. 安装cpolar内网穿透5. 创建远程连接的固定公网地址 前言 本文主要介绍如何在自己的服务器上利用docker搭建 Joplin Server&#xff0c;并对同步进行配置&#xff0c;再结合cpolar内网穿透工具实现公网远程…

学习Stable Diffusion使用 Roop插件轻松换脸(附插件)

在今天的分享中&#xff0c;将了解到如何获取并应用StableDiffusion的Roop插件&#xff0c;以达到完美的面部替换效果。 Roop是一款强大的工具&#xff0c;使您能够轻松地交换面孔并达到逼真的效果。 无论是艺术家、内容创作者&#xff0c;还是仅仅想要尝试图像处理的乐趣&am…

关于Vue2里 v-for和v-if一起用的时候会出现的问题

关于Vue2里 v-for和v-if一起用的时候会出现的问题 &#x1f389;&#x1f389;&#x1f389;欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!&…

使用cmd命令窗口操作mongodb

一、效果显示 二、下载MongoDB 1. 在官网下载安装MongoDB 官网网址&#xff1a;Download MongoDB Community Server | MongoDB 我安装的版本是7.0.14(注意安装到空闲磁盘) 三、启动MongoDB服务 1. 配置环境变量 注意替换为你的路径。 2. 在MongoDB的data下创建db文件夹 在…

51单片机应用开发---二进制、十六进制与单片机寄存器之间的关系(跑马灯、流水灯实例)

实现目标 1、掌握二进制与十六进制之间的转换 2、掌握单片机寄存器与二进制、十六进制之间的转换 3、掌握单片机驱动跑马灯、流水灯的原理 一、二进制与十六进制之间的转换 1、二进制 二进制&#xff08;binary&#xff09;&#xff0c; 是在数学和数字电路中以2为基数的…

计算机毕业设计 乡村生活垃圾管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Java接口与继承:构建灵活系统的基石

在Java编程语言中&#xff0c;接口&#xff08;Interface&#xff09;是一种定义方法规范的类型&#xff0c;它是一种特殊的抽象类&#xff0c;可以被类实现&#xff08;Implement&#xff09;或被其他接口继承&#xff08;Extend&#xff09;。接口是Java实现多态和模块化设计…