MariaDB/MySQL存储过程和函数学习心得

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();

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/3d0650996d891caf1eb475a5123cd232.html