百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

MariaDB/MySQL存储过程和函数(mysql存储过程怎么用)

toyiye 2024-07-05 01:23 25 浏览 0 评论

在MySQL/MariaDB中,存储过程(stored procedure)、存储函数(stored function)、触发器(trigger)、事件(event)统称为存储程序(stored programs)。此外,存储过程和存储函数还合称为stored routines。

对于函数来说,除了存储函数,还有用户自定义函数(UDF,user defined function),在MySQL/MariaDB中,用户自定义函数是存储函数的扩展,它像一个小程序一样,需要编译、安装后才能运行。这和SQL Server对UDF的定义不同,倒是类似于SQL Server的CLR程序。

虽然存储过程和存储函数在功能实现上有些区别,但在使用方法上几乎一致。

1.创建存储过程、函数

在MySQL/MariaDB中创建存储过程、函数的语法如下:其中OR REPLACE是MariaDB 10.1.3版本中才有的,MySQL中不支持OR REPLACE


-- 创建存储过程和函数
CREATE [OR REPLACE] PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body
CREATE [OR REPLACE] FUNCTION sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body

proc_parameter:
    [ IN | OUT | INOUT ] param_name type
func_parameter:
    param_name type

type:
    Any valid MySQL data type
characteristic:
    COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
routine_body:
    Valid SQL routine statement

在MySQL/MariaDB的存储过程和函数中,允许存在DML和DDL语句。且存储过程中还允许(存储函数不允许)使用SQL事务类型的语句,例如提交commit。当然,肯定也支持嵌套其他存储过程或函数。

存储过程的参数有三种类型:IN、OUT和INOUT,下文将详细分析这三种类型参数。

在创建和修改的语法中,需要说明的就是characteristic部分,这部分基本没什么用,但可以了解下它们是干什么的。

  • language sql:表示后面的body部分使用标准SQL语句编写,这是默认的。该选项的作用是为了以后支持非SQL语句书写存储过程和函数的,例如SQL Server中就有使用.NET写的CLR存储过程、函数、触发器等。但目前,这个还没有任何意义。
  • [not] deterministic:deterministic的意思是确定的。这里的意思是函数返回值是明确的,而非具有随机性的值。例如,使用了随机数,使用了now()这样的函数等。not deterministic表示返回值是不确定的,这是系统默认值。当优化器知道函数返回值是确定值时,将选择一个更优化的执行计划。如果返回值是确定的,却定义为not deterministic,则性能会降低,如果返回值是不确定的,却定义为deterministic,则报错。
  • {contains sql|no sql|reads sql data|modifies sql data}:这些是提供给服务器的信息类子句,看上去是约束性语句,但MariaDB不会根据它们做任何检查。也就是说,这些提示符只是给人看的,没有任何作用。contains sql表示body不包含读和写数据的语句,例如SET和DO;no sql表示body不包含SQL语句;reads sql data表示body包含读数据的语句,但不包含写数据的语句,如SELECT。modifies sql data表示body包含写数据的语句,如DELETE/UPDATE;如果没有指定这些特征值,则使用默认值contains sql。
  • sql security:指明执行该程序时以谁的身份执行。definer表示执行时获取创建者的权限,invoker表示以调用者的身份执行,若调用该程序的用户对程序中涉及的对象没有对应的权限则会执行失败(如lisa用户有执行存储过程的权限,但是没有读取存储过程中涉及的表a的权限,那么执行存储过程时因为读表失败而导致执行被拒绝)。默认是definer。
  • comment:程序的注释信息。

当要调用存储过程或函数时,可以使用call命令调用存储过程,如call sp_name();;而函数则可以当作表达式一样进行调用,例如使用select命令select func();,当作表达式赋值给变量set @a=func()

需要注意的是,在MySQL/MariaDB中,因为语句的结束符是分号";",在存储过程或函数创建过程中直接使用分号会导致语句报错。所以当存储过程或存储函数中包含需要使用分号的语句时,应在创建存储过程或函数之前使用delimiter命令来暂时改变语句结束符,在创建完毕之后再改回结束符为分号";"。

例如:

delimiter $
create or replace procedure proc()       -- procedure name
begin                                    -- procedure body
    select * from A;
end $
delimiter ;
--调用存储过程
call proc();

在上面的语句中,首先定义了结束符为$;然后判断了存储过程proc()是否存在,存在则删除,之后才开始创建存储过程。这个存储过程很简单,只是一个select语句。创建语句结束之后,再次使用delimiter命令将结束符改回了分号";"。最后使用call命令进行了存储过程的调用。

以下是一个函数的创建和使用示例:



delimiter $
create or replace function func1()
    returns int
    return (select count(*) from t1);$
delimiter ;
set @c=func1();
select func1(),@c;
+---------+------+
| func1() | @c   |
+---------+------+
|       6 |    6 |
+---------+------+

1.1 存储过程的IN、OUT和INOUT

它们表示的是参数的类型。

IN参数类型表示将调用者给定的值传递给存储过程。存储过程可能会修改这个值,但是对于调用者来说,在存储过程返回结果时,所做的修改是不可见的。

OUT参数类型表示将存储过程的返回值传递给调用者。其初始值为NULL,当存储过程返回时,这个值对调用者来说是可见的。

INOUT参数类型表示由调用者传递值给存储过程,存储过程可能会修改这个值,当存储过程返回的时候,所做的修改对调用者来说是可见的。

对于每个OUT或INOUT类型的参数,当调用者在CALL语句中调用存储过程时,所传递的每个用户变量都可以在存储过程返回的时候获取其值。

默认每个参数都是IN。要指定其他类型的参数,可以在参数名前面使用关键字OUT或INOUT。

(1).IN参数类型。

IN参数类型是指调用者将某个值传递给存储过程,存储过程借用这个值来完成某些操作。

以下是IN类型参数的示例。



create or replace table t1(a int);
insert into t1 values(1),(2),(3),(4),(5),(6);
delimiter $
create or replace procedure proc1(min int,max int)
begin
    select * from t1 where t1.a >= min and t1.a <= max;
end$
delimiter ;
call proc1(3,5);
+------+
| a    |
+------+
|    3 |
|    4 |
|    5 |
+------+

(2).OUT参数类型。

OUT参数类型是指存储过程将某个值通过该参数返回给调用者。因此调用者必须传递一个用户变量给存储过程,用来记录存储过程OUT参数的值。这个用户变量在传递给存储过程之前,可以是一个已赋值的变量,但在传递给存储过程时,将自动初始化为NULL值。

以下是OUT类型参数的示例。在此示例中,传入@a给proc(),最后将count(*)赋值给out参数cnt,cnt代表的就是传入参数@a。



delimiter $
create or replace procedure proc2(out cnt int)
begin
    select count(*) into cnt from A;
end$
delimiter ;
call proc1(@a);
select @a as a;
     a  
--------
       6

(3).INOUT参数类型。

INOUT参数类型指的是调用者和存储过程之间传递的内容可以互相赋值。INOUT有两个过程,一个是IN的过程,这个过程是将调用者指定的值传递给存储过程,另一个是OUT的过程,这个过程是存储过程将某个返回值返回给调用者。因此,调用者传递INOUT参数时,也必须传递一个用户变量。但与OUT不同的是,INOUT的用户变量有初始值,这个初始值会直接应用在存储过程中。而OUT的用户变量虽然也有初始值,但这个初始值会自动转换为NULL。

以下是INOUT参数类型的示例。


/* procedure INOUT */
create or replace table t1(a int);
insert into t1 values(1),(2),(3),(4),(5),(6);
delimiter $
create or replace procedure proc3(INOUT cnt int,min int,max int)
begin
    if cnt <5 then   /* 直接用cnt这个INOUT参数来判断大小,因为它继承了传递时的值 */
        select count(*) into cnt from t1 where t1.a >=min and t1.a <=max;
    else
        select count(*) into cnt from t1;
    end if;
end$
delimiter ;
set @a=3;
set @b=6;
call proc1(@a,3,5);
call proc1(@b,3,5);
select @a,@b;
+------+------+
| @a   | @b   |
+------+------+
|    3 |    6 |
+------+------+

2.修改和删除存储过程、函数

可以使用alter语句修改存储过程、函数,但alter语句只能修改characteristic部分,不支持对body部分和参数部分修改。若要修改它们,只能先删除再创建。


-- 修改存储过程和函数
ALTER {PROCEDURE | FUNCTION} proc_name [characteristic ...]
characteristic:
    COMMENT 'string'
  | LANGUAGE SQL
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }

删除存储过程和函数的方式很简单,直接使用drop命令,但要求有alter权限。

drop {procedure|function} [if exists] sp_name

3.查看存储过程、函数信息

查看存储过程和函数的信息。


show {procedure|function} status like 'pattern'; -- 查看routine的基本信息
show create {procedure|function} proc_name;      -- 查看routine的创建语句
show {procedure|function} code routine_name;     -- 查看MariaDB内部是如何操作routine中各语句的

从information_schema.routines中查看存储过程和函数的信息,这个比show status更详细一点。

select * from information_schema.routines where routine_name='xxx'\G

这里说明下show code功能,这个功能必须要在支持debug的MariaDB上才能使用,可以在编译时使用选项"--with-debug"启用该功能。

例如:


DELIMITER $
CREATE PROCEDURE p1 ()
  BEGIN
    DECLARE fanta INT DEFAULT 55;
    DROP TABLE t2;
    LOOP
      INSERT INTO t3 VALUES (fanta);
      END LOOP;
  END$
delimiter ;
SHOW PROCEDURE CODE p1;
+-----+----------------------------------------+
| Pos | Instruction                            |
+-----+----------------------------------------+
|   0 | set fanta@0 55                         |
|   1 | stmt 9 "DROP TABLE t2"                 |
|   2 | stmt 5 "INSERT INTO t3 VALUES (fanta)" |
|   3 | jump 2                                 |
+-----+----------------------------------------+

其中第一列是从0开始的序列值,表示存储过程中所执行的动作先后顺序。第二列是mariadb要执行的动作,这些动作是基于存储过程中的源语句进行设置的。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码