mysql存储过程和存储函数

2023-10-26

一、存储过程概述

1、mysql存储过程和存储函数是将复杂sql集合在一起,应用程序只需调用即可,不必关注mysql存储过程和存储函数sql逻辑

存储过程预先经过编译的一组sql,存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行。

2、好处

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

3、存储过程和视图、函数的对比
它和视图有着同样的优点,清晰、安全,还可以减少网络传输量。不过它和视图不同,视图是 虚拟表,通常不对底层数据表直接操作,而存储过程是程序化的 SOL,可以 直接操作底层数据表,相比于面向集合的操作方式,能
够实现一些更复杂的数据处理
-旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。相较于函数,存储过程是 没有返回值 的。

4、分类

存储过程的参数类型可以是IN、OUT和INOUT。根据这点分类如下
1、没有参数(无参数无返回)
2、仅仅带 IN 类型 (有参数无返回)
3、仅仅带 OUT 类型 (无参数有返回)
4、既带 IN 又带 OUT (有参数有返回)
5、带INOUT (有参数有返回)
注意: IN、OUT、INOUT 都可以在一个存储过程中带多个

二、存储过程和调用

1、创建储存过程

语法

CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
	存储过程体
END

说明

1、参数

  • IN:输入参数,存储过程读取该参数的值,参数默认类型为IN
  • OUT:输出参数,经存储过程处理后,应用程序可以读取该参数值
  • INOUT:既可以作为输入参数,也可以作为输出参数

2、characteristics 表示创建存储过程时指定的约束条件,取值信息如下:

characteristic 说明
LANGUAGE SQL 说明存储过程由SQL语句组成
[NOT] DETERMINISTIC 指明存储过程执行的结果是否确定,默认为:NOT DETERMINISTIC
{CONTAINS SQL / NO SQL / READS SQL DATA / MODIFIES SQL DATA } 指明子程序使用SQL语句的限制, 默认为:CONTAINS SQL
SQL SECURITY { DEFINER / INVOKER } 指明执行当前存储过程的权限,默认为:DEFINER
COMMENT 'string' 注释信息

3、存储过程中的SQL语句需要放在 BEGIN … END 中

  • BEGIN…END:BEGIN…END 中间包含了多个语句,每个语句都以(;)号为结束符
  • DECLARE:DECLARE 用来声明变量,使用的位置在于 BEGIN…END 语句中间,而且需要在其他语句使用之前进行变量的声明
  • SET:赋值语句,用于对变量进行赋值
  • SELECT… INTO:把从数据表中查询的结果存放到变量中,也就是为变量赋值 

  4、需要设置新的结束标记 DELIMITER 新的结束标记

举例

#sql语句是;结束执行的 ,为了sql组完整执行,DELIMITER 定义新的结束符号,符号自定义
DELIMITER $
CREATE PROCEDURE select_all_data()
BEGIN
	SELECT * FROM emps;
END $
#结束之后再改;
DELIMITER ;


# 举例2:创建存储过程avg_employee_salary(),返回所有员工的平均工资
DELIMITER //
CREATE PROCEDURE avg_employee_salary()
BEGIN
	SELECT AVG(salary) FROM emps;
END //
DELIMITER ;


# 举例3:创建存储过程show_max_salary(),用来查看“emps”表的最高薪资值
DELIMITER //
CREATE PROCEDURE show_max_salary()
BEGIN
	SELECT MAX(salary) FROM emps;
END //
DELIMITER ;


# 举例4:创建存储过程show_min_salary(),查看“emps”表的最低薪资值。并将最低薪资通过OUT参数“ms”输出
DESC emps;

DELIMITER //
CREATE PROCEDURE show_min_salary(OUT ms DOUBLE)
BEGIN
	SELECT MIN(salary) INTO ms FROM emps;
END //
DELIMITER ;


# 举例5:创建存储过程show_someone_salary(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名
DELIMITER //
CREATE PROCEDURE show_someone_salary(IN empname VARCHAR(25))
BEGIN
	SELECT salary FROM emps WHERE last_name = empname;
END //
DELIMITER ;


# 举例6:创建存储过程show_someone_salary2(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名,用OUT参数empsalary输出员工薪资
DELIMITER //
CREATE PROCEDURE show_someone_salary2(IN empname VARCHAR(25), OUT empsalary DOUBLE)
BEGIN
	SELECT salary INTO empsalary FROM emps WHERE last_name = empname;
END //
DELIMITER ;


# 举例7:创建存储过程show_mgr_name(),查询某个员工领导的姓名,并用INOUT参数“empname”输入员工姓名,输出领导的姓名
DELIMITER //
CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(25))
BEGIN
	SELECT last_name INTO empname FROM emps
	WHERE employee_id = (SELECT manager_id FROM emps WHERE last_name = empname);
END //
DELIMITER ;

2、存储过程调用

调用格式

CALL 存储过程名(实参列表);
若要执行其他数据库中的存储过程,需要指明数据库名: CALL dbname.procname;

  • 调用IN模式的参数:
    CALL procname(‘值’);
  • 调用OUT模式的参数:
    SET @name;
    CALL procname(@name);
    SELECT @name;
  • 调用INOUT模式的参数:
    SET @name=值;
    CALL procname(@name);
    SELECT @name;

以此调用上面1中创建好存储过程

# 2.2节中举例1
CALL select_all_data();

# 2.2节中举例2
CALL avg_employee_salary();

# 2.2节中举例3
CALL show_max_salary();

# 2.2节中举例4
SET @ms;
CALL show_min_salary(@ms);
SELECT @ms;

# 2.2节中举例5
SET @empname='Abel';
CALL show_someone_salary(@empname);

# 2.2节中举例6
SET @empname='Abel';
SET @empsalary;
CALL show_someone_salary2(@empname, @empsalary);
SELECT @empname, @empsalary;

# 2.2节中举例7
SET @empname='Abel';
CALL show_mgr_name(@empname);
SELECT @empname;
# 举例8:创建存储过程,实现累加运算,计算 1+2+…+n 等于多少
DELIMITER //
CREATE PROCEDURE add_num(IN n INT)
BEGIN
	DECLARE i INT;
	DECLARE `sum` INT;
	SET i = 1;
	SET `sum` = 0;
	
	WHILE i <= n DO
		SET `sum` = `sum` + i;
		SET i = i + 1;
	END WHILE;
	
	SELECT `sum`;
END //
DELIMITER ;

CALL add_num(50);

 可以通过SELECT语句把程序的中间结果查询出来,来调试一个SQL语句的正确性。

三、存储函数创建和调用

1、语法格式

说明:

  1. 参数列表:指定参数为IN,OUTINOUT只对PROCEDURE是合法的,FUNCTION中总是默认为IN参数
  2. RETURNS type 语句表示函数返回数据的类型
  3. characteristic 创建函数时指定对函数的约束,取值与存储过程相同
  4. 函数体也用BEGIN...END来表示SQL代码的开始和结束

调用方式

SELECT 函数名(实参列表); 

注意:若在创建存储函数中报错“ you might want to use the less safe log_bin_trust_function_creators variable ”,有两种处理方法:

  • 方式1:加上必要的函数特性“[NOT] DETERMINISTIC”和“{CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
  • 方式2:SET GLOBAL log_bin_trust_function_creators = 1;

 举例

# 举例1:创建存储函数,名称为email_by_name(),参数定义为空,该函数查询Abel的email,并返回,数据类型为字符串型
SET GLOBAL log_bin_trust_function_creators = 1;

DESC emps;

DELIMITER //

CREATE FUNCTION email_by_name()
RETURNS VARCHAR(25)
BEGIN
	RETURN (SELECT email FROM emps WHERE last_name = 'Abel');
END //

DELIMITER ;

SELECT email_by_name();


# 举例2:创建存储函数,名称为email_by_id(),参数传入emp_id,该函数查询emp_id的email,并返回,数据类型为字符串型
DELIMITER //

CREATE FUNCTION email_by_id(emp_id INT)
RETURNS VARCHAR(25)
BEGIN
	RETURN (SELECT email FROM emps WHERE employee_id = emp_id);
END //

DELIMITER ;

SELECT email_by_id(100);


# 举例3:创建存储函数count_by_id(),参数传入dept_id,该函数查询dept_id部门的员工人数,并返回,数据类型为整型
DELIMITER //

CREATE FUNCTION count_by_id(dept_id INT)
RETURNS INT
BEGIN
	RETURN (SELECT COUNT(*) FROM emps WHERE department_id = dept_id);
END //

DELIMITER ;

SELECT count_by_id(100);

 

2、对比存储函数和存储过程

关键字 调用语法 返回值 应用场景
存储过程 PROCEDURE CALL 存储过程() 理解为有0个或多个 一般用于更新
存储函数 FUNCTION SELECT 存储函数() 只能是一个 一般用于查询结果为一个值并返回时

存储函数可以放在查询语句中使用,存储过程不行。

四、存储过程和函数的查看、修改、删除

1、查看

使用SHOW CREATE语句查看存储过程和函数的创建信息

SHOW CREATE {PROCEDURE | FUNCTION} 存储过程或函数名;

SHOW CREATE PROCEDURE avg_employee_salary;

SHOW CREATE FUNCTION count_by_id;

使用SHOW STATUS语句查看存储过程和函数的状态信息

 SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'PATTERN'];

SHOW PROCEDURE STATUS LIKE 'avg_employee_salary';

SHOW PROCEDURE STATUS;	# 列出所有存储过程信息

SHOW FUNCTION STATUS LIKE 'count_by_id';

SHOW FUNCTION STATUS;	# 列出所有存储函数信息

information_schema.Routines表中查看存储过程和函数的信息 

SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = '存储过程或函数名' [AND ROUTINE_TYPE = {'PROCEDURE | FUNCTION'}];

SELECT * FROM information_schema.Routines;

SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = 'avg_employee_salary' AND ROUTINE_TYPE = 'PROCEDURE';

2、修改 

修改存储过程或函数,不影响存储过程或函数的功能,只是修改相关特性
ALTER {PROCEDURE | FUNCTION} 存储过程或函数名 [characteristic ...];

# 举例1:修改存储过程 show_someone_salary 的定义。将读写权限改为MODIFIES SQL DATA,并指明调用者可以执行
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = 'show_someone_salary';

ALTER PROCEDURE show_someone_salary
MODIFIES SQL DATA
SQL SECURITY INVOKER;

# 举例2:修改存储函数 email_by_name 的定义。将读写权限改为READS SQL DATA,并加上注释信息“FIND NAME”
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = 'email_by_name';

ALTER FUNCTION email_by_name
READS SQL DATA
COMMENT 'FIND NAME';

3、删除

DROP {PROCEDURE | FUNCTION} [IF EXISTS] 存储过程或函数名;

DROP PROCEDURE IF EXISTS show_someone_salary;

DROP FUNCTION IF EXISTS email_by_name;

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mysql存储过程和存储函数 的相关文章

  • 根据日期顺序排名

    我的数据如下 Heading Date A 2009 02 01 B 2009 02 03 c 2009 02 05 d 2009 02 06 e 2009 02 08 我需要如下排名 Heading Date Rank A 2009 02
  • 如何在 MySQL 中测试 Select for Update

    我正在表演SELECT FOR UPDATE或 InnoDB 表的行级锁定 我的目的是只有一个请求可以读取同一行 因此 如果两个用户同时请求相同的数据 其中只有一个人获取数据 即第一个触发查询的人 但是我如何测试锁定是否已放置 因为我正在通
  • 如何通过子 POJO 的属性过滤复合 ManyToMany POJO?

    我有两个像这样的房间实体 Entity public class Teacher implements Serializable PrimaryKey autoGenerate true public int id ColumnInfo n
  • 非常大的字段会对 MySQL 数据库产生负面影响吗?

    我目前正在使用 Django 构建一个网站 并希望托管用户生物样式页面 该页面可能长达几 KB 这些字段不一定需要搜索 但在查找用户名时确实需要提供 将这些数据存储在数据库中会产生负面影响吗 如果我使用带有数据库链接的静态文本文件 我的服务
  • 快速查询最新记录的方法?

    我有一张这样的表 USER PLAN START DATE END DATE 1 A 20110101 NULL 1 B 20100101 20101231 2 A 20100101 20100505 在某种程度上 如果END DATE i
  • 让登录更安全

    我已使用此代码进行管理员登录 仅当用户输入正确的用户名和密码时才应打开loginhome php 但后来我意识到这根本不安全 任何人都可以直接访问 mywebsite loginhome php 而无需登录 注销后 可以使用后退按钮打开 l
  • 在 SQL Server 上执行分页的最佳方式是什么?

    我有一个数据库超过200万记录 我需要执行分页以在我的 Web 应用程序上显示 该应用程序每页必须有 10 条记录DataGrid 我已经尝试使用ROW NUMBER 但是这种方式会选择所有 200 万条记录 然后只得到 10 条记录 我也
  • 如何通过 SQL 表关联 SQL 中的实体

    我是数据库设计的初学者 我需要为项目创建数据库 我可以用面向对象的术语解释我想要做什么 值得庆幸的是 数据库专家会很友善地向我解释如何在数据库方面处理这个问题 我想创建一个与位置实体 州 城市 有关系的用户 ID 名称 实体 所以在编程语言
  • 将庞大数据库从亚马逊RDS导出到本地mysql

    我在 Amazon RDS 上有一个 mysql 数据库 大约 600GB 数据 我需要将其移回本地专用服务器 但我不知道从哪里开始 每次我尝试初始化 sqldump 时它都会冻结 有没有办法将其移至 S3 甚至可能在开始下载之前将其分成更
  • Mysql用in语句限制

    我正在写一个查询 SELECT user bookmarks id as user bookmark id bookmark id user bookmarks user id bookmark url bookmark website b
  • 数字表与递归 CTE 生成一系列数字

    为什么使用数字表比使用递归 CTE 动态生成它们要快得多 在我的机器上 给定一张桌子numbers单列n 主键 包含从1到100000的数字 查询如下 select n from numbers 大约需要 400 毫秒才能完成 使用递归 C
  • 从 Getdate() 获取时间

    我想采取Getdate 结果 例如 2011 10 05 11 26 55 000 into 11 26 55 AM 我看过其他地方并发现 Select RIGHT CONVERT VARCHAR GETDATE 100 7 这给了我 11
  • 日期语句之间的 JPQL SELECT [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我想将此 SQL 语句转换为等效的 JPQL SELECT FROM events WHERE events date BETWE
  • 学说迁移后备

    我们正在使用原则迁移 当迁移包含多个操作并且其中一个操作失败时 通常会出现问题 例如 如果迁移添加了 5 个外键 其中第 5 个失败 而字段长度不同 则修复字段错误并重新生成迁移不会not修复整个问题 而现在出现一个与 4 个密钥已存在有关
  • 从Django中具有外键关系的两个表中检索数据? [复制]

    这个问题在这里已经有答案了 This is my models py file from django db import models class Author models Model first name models CharFie
  • Mysql插入表后不显示右单引号(’)

    我有一个名为 测试 的表 我插入了一行 其中包含unicode字符右单引号 0x2019在名称字段中 SQL insert into Testing values Sno Name Address insert into Testing v
  • Spark SQL 中的 SQL LIKE

    我正在尝试使用 LIKE 条件在 Spark SQL 中实现联接 我正在执行连接的行看起来像这样 称为 修订 Table A 8NXDPVAE Table B 4 8 NXD V 在 SQL Server 上执行联接 A revision
  • MySQL 转储未知选项“-no-beep”

    在旧服务器上我使用了mysql转储命令来备份 MySQL 数据库 在新服务器上 MySQL 版本为 5 6 相同的命令给出了错误 unknown option no beep 无论它插入什么 我也在互联网上搜索过 但找不到任何帮助 在 my
  • 如何通过SQL查询检查是否有JSON函数?

    有SQL 2016 中的 JSON 函数 https learn microsoft com en us sql t sql functions json functions transact sql例如 JSON VALUE JSON Q
  • post php mysql 的拆分关键字

    我有一个表存储帖子 ID 它的标签如下 Post id Tags 1 keyword1 keyword2 keyword3 我想循环遍历该表中的每一行并执行以下操作 将关键字1 关键字2 关键字3放入新表中 word id word val

随机推荐

  • typescript基础之object和Object

    TypeScript 的 object 和 Object 是两种不同的类型 它们的区别和用途如下 object 类型是 TypeScript 2 2 引入的新类型 它表示非原始对象 也就是除了 number string boolean s
  • 实时时钟电路DS1302的原理及应用

    2006 05 11 10 10 39 实时时钟电路DS1302的原理及应用
  • 使用windeployqt.exe打包QT工程,windows系统可执行程序

    前言 因为自己打包qt程序遇到点问题 提示0xc000007b错误 发现是因为打包工具和工程编译工具不对应导致 于是为了记录打包方法 有了此篇文章 记录使用windeployqt exe打包qt工程在windows系统的可执行文件 一 确定
  • adb install 命令参数

    adb install 6个参数描述 t 允许测试包 l 锁定该应用程序 s 把应用程序安装到sd卡上 g 为应用程序授予所有运行时的权限 r 替换已存在的应用程序 也就是说强制安装 d 允许进行将见状 也就是安装的比手机上带的版本低
  • activiti-serviceTask(服务任务)

    Activiti服务任务 serviceTask Activiti服务任务 serviceTask 作者 邓家海 都有一段沉默的时间 等待厚积薄发 应用场景 当客户有这么一个需求 下一个任务我需要自动执行一些操作 并且这个节点不需要任何的人
  • 一文让你深刻理解异步请求池-DNS解析与实现

    一 DNS概念简述 DNS Domain Name Service 域名解析服务 工作在应用层 是互联网的一项服务 它作为将域名和IP地址相互映射的一个分布式数据库 能够使人更方便地访问互联网 DNS监听在TCP和UDP端口53 FQDN
  • SpringMVC系列(十)(处理静态资源)和...

  • 通俗理解泰勒公式

    本博客只用于自身学习 如有错误 虚心求教 在维基百科上的解释 在数学中 泰勒公式 英语 Taylor s Formula 是一个用函数在某点的信息描述其附近取值的公式 这个公式来自于微积分的泰勒定理 Taylor s theorem 泰勒定
  • 计算方法——C语言实现——迭代法求解线性方程组

    最近在上计算方法这门课 要求是用MATLAB做练习题 但是我觉得C语言也很棒棒啊 题目 和直接法不同 迭代法是一种逐次逼近的方法 将复杂问题简单化 求比较大的方程组时一般都不会用直接法 迭代法有好几种 这里使用了Jacobi迭代与Gauss
  • 8.4收官之战非农蓄力能否引爆黄金单边行情?

    近期有哪些消息面影响黄金走势 黄金多空该如何研判 黄金消息面解析 周五 8月4日 亚洲时段 现货黄金在近三周低位窄幅震荡 目前交投于1937 60美元 盎司附近 美联储7月决策符合预期 如期加息25个基点 虽然美国通胀增速放缓 但仍高于美联
  • Git 大文件push失败

    目录 1 下载并安装Git Large File Storage命令行扩展 2 配置lfs跟踪的文件 3 commit 并push到远程仓库 由于git有push文件的大小限制 100MB 因此如果push操作中右超过100MB的文件 就会
  • 抽签小程序(C语言随机数),C# 抽签小程序

    设计背景 设置一个Excel名单表 对名单进行随机抽取 设计思路 使用Timer定时器 运行定时器进行名单随机滚动 停止定时器获得抽签结果 相关技术 随机数 Excel读取 导出 XML文档读写 相关类库 C1 C1Excel Excel操
  • 《深入浅出话数据结构》系列之什么是B树、B+树?为什么二叉查找树不行?

    本文将为大家介绍B树和B 树 首先介绍了B树的应用场景 为什么需要B树 然后介绍了B树的查询和插入过程 最后谈了B 树针对B树的改进 在谈B树之前 先说一下B树所针对的应用场景 那么B树是用来做什么的呢 B树是一种为辅助存储设计的一种数据结
  • 达梦DCA认证培训和考试

    本人有幸参加了达梦DCA认证培训并参加了认证考试 培训内容包括 第一天 国产数据库现状及未来 DM8企业版安装 创建数据库及数据库实例管理 DM8体系结构 第二天 表空间管理 用户管理 DMSQL 第三天 模式对象管理 备份还原 配置作业
  • 数据结构课程设计 最小生成树,拓扑排序以及最短路径

    通信网络的架设问题 问题描述 若要在n 10 个城市之间建设通信网络 只需要架设n 1条线路即可 如何以最低的经济代价建设这个通信网 是一个网的最小生成树问题 基本要求 1 利用二种方法 Prim算法和克鲁斯卡尔 Kruskual 生成网中
  • 阿里Java后端电话面试

    生平第一次面试 还是阿里 非常紧张 因为是校招 所以面的比较简单 都是我简历上说熟悉的东西 回答的不是很理想 面试官说我广度还行 深度差的比较多 面试官 你好同学 我是蚂蚁金服的 现在方便面试吗 我 方便方便 面试官 请简单介绍一下自己 这
  • Fultter学习日志(2)-构建第一个flutter应用

    依照上一篇中我们新建的flutter应用 让我们更改pubspec yaml中的内容为 name namer app description A new Flutter project publish to none Remove this
  • 在 Python Lambda 中使用 Await

    异步编程不是多线程或多进程 相反 它是并发编程 我们可以运行一个可能长时间运行的任务 并允许我们的程序在该任务仍在运行时响应其他任务 而不是等待完成 对于异步编程 HTTP 请求操作或用户选择可能会花费大量时间 因此 允许其他任务在这些操作
  • 100天精通Python(数据分析篇)——第72天:Pandas文本数据处理方法之判断类型、去除空白字符、拆分和连接

    文章目录 每篇前言 一 Python字符串内置方法 1 判断类型 2 去除空白字符 3 拆分和连接 二 Pandas判断类型 1 str isspace 2 str isalnum 3 str isalpha 4 str isdecimal
  • mysql存储过程和存储函数

    一 存储过程概述 1 mysql存储过程和存储函数是将复杂sql集合在一起 应用程序只需调用即可 不必关注mysql存储过程和存储函数sql逻辑 存储过程预先经过编译的一组sql 存储在 MySQL 服务器上 需要执行的时候 客户端只需要向