首页 > 数据库 >MySQL存储过程

MySQL存储过程

时间:2023-11-22 13:56:42浏览次数:41  
标签:语句 存储 函数 MySQL 参数 SQL 过程

存储过程

1. 存储过程概述

概述:存储过程的英文是"stored procedure"。它的思想很简单,"就是一组经过"预先编译"的 SQL 语句的封装"。

执行过程:存储过程预先存储在 MySql 服务器上,需要执行的时候,"客户端只需要向服务器端发送调用存储过程的命令",服务端就可以把预先存储好的这一系列 SQL 语句全部执行

好处:

  1. 简化操作,提高了sql语句的重用性,减少了开发程序员的压力
  2. 减少操作过程中的失误,提高效率
  3. 减少网络传输(客户端只需通过命令调用即可)
  4. 减少了 SQL 语句暴露的风险,提高了数据查询的安全性
  5. SQL 语句安全性高,可以设定数据库用户的访问权限

存储过程和函数的对比:

使用存储过程就像使用函数一样简单,直接通过调用存储过程名即可。相较于函数,存储过程是没有返回值的。

2. 分类

存储过程的参数类型可以是 IN,OUT和INOUT。根据这点分类如下:

  1. 没有参数(无参数无返回)
  2. 仅仅带 IN 类型(有参数无返回)
  3. 仅仅带 OUT 类型(无参数有返回)
  4. 即带 IN 又带 OUT (有参数有返回)
  5. 带 INOUT (有参数有返回)

注意:IN,OUT,INOUT 都可以在一个存储过程中带多个。

3. 创建存储过程

3.1 语法分析

语法格式:

delimiter $
# 修改sql语句的结束标记为 $
create procedure 存储过程名称(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
begin
# 存储过程体(方法体)

end $
delimiter ;
# 修改sql语句的结束标记为 ;

类似于java中的方法(void):

修饰符 void 方法名(参数类型 参数名,...){
// 方法体
}

3.1.1 无参数创建

delimiter $
create procedure 存储过程名称()
begin
# 存储过程体
end $
delimiter ;

3.1.2 带(OUT)参数创建

delimiter $
create procedure 存储过程名称(OUT 参数名 参数类型,...)
begin
# 存储过程体
# 输出参数:结果集 into = 参数名 例如:select 字段 into out参数名 from .......
end $
delimiter ; 

3.1.3 带(IN)参数创建

delimiter $
create procedure 存储过程名称(IN 参数名称 参数类型,...)
begin
# 存储过程体
# 使用输入参数:直接使用 参数名称即可 例如 select * from xld where id = 参数名称;
end $
delimiter ;

3.1.4 带(INOUT)参数创建

delimiter $
create procedure 存储过程名称(INOUT 参数名称 参数类型,...)
begin
# 存储过程体
# 使用输入输出参数:支持 IN/OUT 的语法 例如:select 字段 into 参数名称,字段,... from xld where id = 参数名称; 
end $
delimiter ;

3.2 说明

3.2.1 参数前面的符号的意思

  • IN:当前参数为输入参数,也就是表示入参;

存储过程"只是读取这个参数的值",如果没有定义参数种类,默认就是 IN,表示输入参数。

  • OUT:当前参数为输出参数,也就是表示出参;

当执行完成之后,调用这个存储过程的客户端或者应用程序就 可以读取这个参数,得到这个参数的返回的值了

  • INOUT:当前参数既可以为输入参数,也可以为输出参数。

3.2.2 形参类型

形参类型可以是 MySql 数据库中的任意类型。

3.2.3 characteristics 特征(约束条件)

该类型是用来表示创建存储过程时指定的对存储过程的约束条件,其取值信息如下:

LANGUAGE SQL
[NOT] DETERMINISTIC
{CONTAINS SQL,NO SQL,READS SQL DATA,MODIFIES SQL DATA}
SQL SECURUTY {DEFINER,INVOKER}
COMMIT '描述'
  • LANGUAGE SQL

    说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL。

  • [NOT] DETERMINISTIC:指明存储过程执行的结果是否确定?

    1. DETERMINISTIC 表示结果是确定的。每次执行存储过程是,相同的输入会得到相同的出输出。

    2. NOT DETERMINISTIC 表示结果是不确定的,相同的输入可能得到不同的输出。

    3. 默认为:NOT DETERMINISTIC 。

  • {CONTAINS SQL,NO SQL,READS SQL DATA,MODIFIES SQL DATA}:指明子程序使用SQL语句的限制

    1. CONTAINS SQL:表示当前存储过程的子程序包含SQL语句,但不包含读写数据的SQL语句。

    2. NO SQL:表示当前存储过程的子程序中不包含任何SQL语句

    3. READS SQL DATA:表示当前存储过程的子程序中只包含读数据的SQL语句

    4. MODIFES SQL DATA:表示当前存储 过程的子程序中只包含写数据的SQL语句

    5. 默认为:CONTAINS SQL

  • SQL SECURUTY {DEFINER,INVOKER}:指明当前存储过程的权限。那些用户能够执行那些存储过程?

    1. DEFINER:表示只有当前存储过程的创建者或者定义者才能执行当前存储过程。

    2. INVOKER:表示拥有当前存储过程的访问权限的用户能够执行当前存储过程。

    3. 默认为:DEFINER

  • COMMENT '描述' 注释信息,描述存储过程的信息。

3.2.4 存储过程体

存储过程体可以有多条 SQL 语句,如果仅仅只有一条 SQL 语句,则可以省略 BEGIN 和 END。当然存储过程都是些需要复杂的 SQL 语句组成的。

....

3.2.5 设置新的结束标记

DELIMITER 新的结束标记
# 一般结合 DELIMITER ; 使用

4.存储过程的调用

4.1 无参数调用

call 存储过程名称();
# 例如
CALL xld_procedure();

4.2 有(OUT/IN/INOUT)参数调用

call 存储成功名称(@参数);
# 例如
CALL xld_procedure(@param);
# 查看该参数值
select @param;
# 创建/设置自定义变量
set @param = '值'; 

二. 存储函数

1.创建存储函数

1.1 语法分析

语法格式:

delimiter $
create function 函数名(参数名称 参数类型)
returns type #返回值类型 
characr...
begin
# 函数体
return (select 语句 ... );
end $
delimiter ;

类似于java中的方法:

修饰符 返回值类型 方法名(参数类型 参数名,...){
// 方法体
  	return 返回值;  
}

1.2 举例

delimiter $
create function 函数名称()
returns 返回值类型
charact ... # 必要的特性配置
# 1.函数执行结果是否确定
# 2.指明子程序对 SQL 语句的限定(可以指明多个 ... 一般指明包含SQL语句和读的SQ语句)
begin
return (select ... );
end $
delimiter ;

例如

# 无参
delimiter $
CREATE FUNCTION xld_function()
RETURNS VARCHAR(25)
	NOT DETERMINISTIC
	CONTAINS SQL
	READS SQL DATA
BEGIN
RETURN (SELECT DISTINCT id FROM xld WHERE id = 2 ); #注意函数的返回值只能是一个值
END $
delimiter ;
# 有参
delimiter $
CREATE FUNCTION xld_function_id(xld_id INT)
RETURNS INT
	NOT DETERMINISTIC
	CONTAINS SQL
	READS SQL DATA
BEGIN
RETURN (SELECT DISTINCT id FROM xld WHERE id = xld_id ); #注意函数的返回值只能是一个值
END $
delimiter ;

1.3 函数创建时的问题

错误:[Err] 1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (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}"
# 在 returns 后 添加以下必要的配置
delimiter $
CREATE ...
RETURNS INT
    not deterministic
    contains sql
    reads sql data
BEGIN
# 函数体
END $
delimiter ;
  • 解决方式2:
set global log_bin_trust_function_creators = 1;

2 说明

2.1 参数列表

参数列表:指定参数为IN,OUT或者INOUT只对PROCEDURE是合法的,FUNCTION中总默认为IN参数。

2.2 returns 返回值

  • RETURNS type 语句表示函数返回数据的类型。

  • returns 子句只能对 function 做指定,对函数而言这是"强制"的。它用来指定函数的返回类型,而且函数必须包含一个"return value"语句

2.3 characteristics 特征(约束条件)

在创建函数时指定的对函数的约束。取值和创建存储过程时相同。注意:在函数中必须指定。

2.4 其他

函数体可以有多条 SQL 语句,如果仅仅只有一条 SQL 语句,则可以省略 BEGIN 和 END。

3. 存储函数的调用

select 函数名(实参列表); # 实参列表已 , 分割

4. 对比存储函数和存储过程

名称 关键字 调用语法 返回值 应用场景
存储过程 procedure call 存储过程名称(实参) 有0个或者多个(理解为引用传递) 呵呵哒,经验之谈...
存储函数 function select 存储函数名称(实参) 只能是一个 一般用于查询结果为一个值并要求返回时使用

此外,存储函数可以放在查询语句中使用,存储过程不行,反之存储过程的功能更加强大,包括能够执行对表的操作(创建表,删除表等)和事务操作,这些功能是存储函数不具备的

三. 存储过程和函数查看,修改,删除

1.查看

1.1 show create {procedure|function}查看(创建信息)

show create {procedure|function} 存储过程或函数名称;
# 例如
SHOW CREATE FUNCTION xld_function;
/
SHOW CREATE PROCEDURE xld_procedure;

1.2 show {procedure|function} status 查看(状态信息)

show {procedure|function} status like '存储过程或函数全名';
# 例如
SHOW PROCEDURE STATUS LIKE 'xld_procedure';
/
SHOW FUNCTION STATUS LIKE 'xld_function';

1.3 从 information_schema.ROUTINES 表中查看(详细信息)

select * from information_schema.ROUTINES 
where ROUTINE_NAME = '存储过程或函数名称' AND ROUTINE_TYPE = 'FUNCTION|PROCEDURE' # 注意 type 的值必须大写
# 例如
SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'xld_function' AND ROUTINE_TYPE = 'FUNCTION'
/
SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'xld_procedure' AND ROUTINE_TYPE = 'PROCEDURE'

2. 修改 - alter

注意:修改存储过程或函数,不影响存储过程或函数的功能,只是修改相关特性。使用 ALTER 语句实现。

alter {procedure|function} 存储过程或函数名称 charact....
# 例如
ALTER FUNCTION xld_function SQL SECURITY INVOKER COMMENT '小林当测试函数';
/
ALTER PROCEDURE xld_procedure COMMENT '小林当测试存储过程';

3. 删除 - drop

drop {procedure|function} [if existe] 存储过程或函数名称;
# 例如
DROP PROCEDURE IF EXISTS xld_procedure_drop;
/
DROP FUNCTION IF EXISTS xld_function_drop

关于存储过程使用的争议

尽管存储过程有诸多优点,但是对于存储过程的使用,一直都存在这很多争议。例如有些公司对于大型项目要求使用存储过程,而有些公司明确禁止使用存储过程,为什么会是这样的呢?

1. 优点

  • 存储过程可以一次编译多次使用。创建时进行编译,之后的使用不需要编译,直接运行,提升SQL的执行效率
  • 可以减少开发工作量。将代码"封装"成模块,实现模块之间可以重复使用。
  • 存储过程的安全性强。可以设定用户的使用权限。
  • 可以减少网络传输量。客户端只需使用简单的调用命令调用即可。减少网络传输量。
  • 良好的封装性。将多条 SQL 语句封装成一个存储过程,只需连接一次调用即可。

2. 缺点

基于上面这些优点,不少大公司都要去大型项目使用存储过程,比如微软,IBM 等公司。但是国内的阿里不推荐开发人员使用,这是为什么?

阿里开发规范
禁止使用存储过程,因为存储过程难以调试和扩展,更没有移植性
  • 可移植性差。存储过程不能跨库移植,MySql ,Oracle 和 SQL server 之间不能相互移植
  • 调式困难。只有少数 DBMS 支持存储过程的调试,复杂的存储过程,开发维护都不容易。有但要收费
  • 存储过程的版本管理很困难。数据表中的索引发送变化,可能会导致存储过程失效。存储过程本身没有版本控制
  • 重点:它不适合高并发的场景。分库分表时,对数据库扩展要求很高,存储过程会的更加难以维护

3. 小结

存储过程即方便,又有局限性。尽管不同的公司对存储过程的态度不一,但是对于我们开发人员来说,不论在怎么样,掌握存储过程都是必备的技能之一。

四. 口诀

操作存储过程简单口诀:c 创 - d 删 - a 修改(procedure)

操作存储函数简单口诀:c 创 - d 删 - a 修改(function)

五. 存储过程和函数中定义和使用变量(局部变量)

标签:语句,存储,函数,MySQL,参数,SQL,过程
From: https://www.cnblogs.com/xiaolindang/p/17848848.html

相关文章

  • MySQL视图
    视图(view)1.常见的数据库对象对象描述表(table)表是存储数据的单元,以行和列的形式存在,列就是字段,行就是记录数据字典(系统表)就是系统表,存放数据库相关信息的表。系统表的数据通常由数据库系统维护,程序员通常不应该修改,只能查看约束(constraint)执行数据校验的规则,......
  • mysql8下载安装及配置
    一、下载官网地址:https://dev.mysql.com/downloads/mysql/8.0.html选择“downloads”-->"mysqlcommunityserver",如下图所示:向下滑动页面,找到你电脑适配的版本,点击“download”,如下图:页面跳转,不需要注册和登陆,点击“Nothanks,juststartmydownload.......
  • mysql 处理 json 字段
    1.查看包含json字段的表信息mysql>desctab_json;+-------+------------+------+-----+---------+----------------+|Field|Type|Null|Key|Default|Extra|+-------+------------+------+-----+---------+----------------+|id|bigint(20)......
  • java类转mysql表创建语句
    packagecn.eangaie.cloud.wx3562;importcn.hutool.core.io.FileUtil;importcn.hutool.core.lang.Console;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;importio.swagger.annotations.ApiModelProper......
  • MySQL-重置主键自动递增值-从头开始
    如果你想要重置MySQL数据库中的AUTO_INCREMENT值并让它从头开始增加新的ID,请按照以下步骤进行操作:首先,确定你要修改的表格名和要修改的字段名。例如,假设你有一个名为“users”的表格,并且该表格中的主键字段名为“id”。然后,执行以下SQL命令来更改该字段的当前自动递增计数器:ALT......
  • DB2存储过程,输出数据集的几种方式汇总
    1----------------1、直接输出数据集-------------------2CREATEORREPLACEPROCEDURE"BI_DM"."SP_XINGUANQUERY"(3startdatevarchar(20)4,enddatevarchar(20)5,querydiagnamevarchar(64)6)7dynamicresultsets18LAN......
  • mysql无法登陆,报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' (
    问题描述在使用命令行登录MySQL时出现了下述问题: 出错原因usingpassword:NO:表示输入没有输入密码就尝试登陆了usingpassword:YES:表示输入了密码,但密码错误 解决方案:修改密码1.修改mysql配置文件my.cnf。在 [mysqld]增加skip-grant-tables 无密码进入mys......
  • 【MySQL】配置文件
    #Disablingsymbolic-linksisrecommendedtopreventassortedsecurityrisks#symbolic-links=0#Settingsuserandgroupareignoredwhensystemdisused.#Ifyouneedtorunmysqldunderadifferentuserorgroup,#customizeyoursystemdunitfilefor......
  • MySql 中 DATEDIFF() 用法
    DATEDIFF函数用于计算两个日期之间的差值,并以天数返回结果。它的语法如下:DATEDIFF(end_date,start_date)其中,end_date和start_date是要计算差值的结束日期和起始日期。以下是一个示例,计算两个日期之间的天数差值:SELECTDATEDIFF('2023-11-21','2023-11-01')ASdays_di......
  • MySQL8.0新特性
    MySql8的其他新特性1.MySQL8新特性概述MySQL从5.7版本直接跳跃发布了8.0版本,可见这是一个令人兴奋的里程碑版本。MySQL8版本在功能上做了显著的改进与增强,开发者对MySQL的源代码进行了重构,最突出的一点是多MySQLOptimizer优化器进行了改进。不仅在速度上得到了改善,还为......