delimiter
介绍函数和存储过程之前,需要先了解delimiter。
delimiter是mysql的sql命令分隔符(命令结束标识),出现分隔符表示命令已经结束了,mysql会执行分隔符之前的sql语句。
delimiter默认是分号;
。
如创建函数或存储过程时,中间有多个分号;
,但并不希望mysql遇见分号就马上执行,这时就可以使用delimiter改变分隔符。
在函数创建完成后,再用delimiter还原成分号;
。
示例:
--输入一个名称,返回一个询问是否单身的字符串
drop function if exists `test_func`;
delimiter /
create function `test_func`(param varchar(20)) returns varchar(50) charset utf8 deterministic
begin
return concat('hello',param,'! you are single dog?');
end
/
delimiter ;
--charset utf8:返回的字符串时utf8格式的。
--deterministic :指明存储过程或函数执行的结果是否正确。deterministic表示结果是确定的。每次执行存储过程或函数时,相同的输入会得到相同的输出。
--not deterministic表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为not deterministic。
--concat函数支持一个或者多个参数,参数类型可以为字符串类型也可以是非字符串类型,对于非字符串类型的参数mysql将尝试将其转化为字符串类型,concat函数会将所有参数按照参数的顺序拼接成一个字符串做为返回值。
代码delimiter /
表示将分隔符修改成/
,你也可以修改成任意字符(或多个),只要你的函数或存储过程的代码中不会出现该字符即可。
如将delimiter /
替换成:delimiter #
、delimiter //
、delimiter ;;
、delimiter _end
也是可以的。
千万别忘了在函数定义完成后还原回分号。
函数
函数不能返回表的结果集,如果需要返回表结果集请使用存储过程,或者存入临时表后查询临时表。
函数中不支持事务操作,所以不要在函数中进行增删改操作。
基本结构:
create funciton 存储过程名称(参数名称 参数类型) returns 返回值类型
begin
要执行的sql语句 ;
end;
代码示例
--修改指定id的用户名称,并返回受影响的行数。
drop function if exists test_func;
delimiter /
create function test_func(param1 int,param2 varchar(10))returns int
begin
update user set user_name=param_in2 where user_id=param_in1;
return (select row_count());
end /
delimiter ;
--还有个和row_count的类似的found_rows,found_rows用来获取最后一次查询到行数
调用
select test_func(1,'李四');
存储过程
存储过程官方完整结构:
characteristic:
language sql
| [not] deterministic
| { contains sql | no sql | reads sql data | modifies sql data }
| sql security { definer | invoker }
| comment 'string'
routine_body:
valid sql procedure statement or statements
基本结构
完整结构不明白没关系,大多数时候其实只用到基本结构。
create procedure 存储过程名称([in|out|inout] 参数名称 参数类型)
begin
要执行的sql语句 ;
end;
--in输入,out输出,inout输入输出
--mysql存储过程参数如果不显式指定“in”、“out”、“inout”,则默认为“in”。
代码示例
--修改指定id的用户名称,并返回受影响的行数。
drop procedure if exists test_proc;
delimiter /
create procedure test_proc(in param_in1 int,IN param_in2 varchar(10), out param_out varchar(10))
begin
update user set user_name=param_in2 where user_id=param_in1;
set param_out=(select row_count());
end /
delimiter ;
另外也可以不通过输出参数来返回:
--返回全部用户以及所有姓王的用户
drop procedure if exists test_proc;
delimiter /
create procedure test_proc()
begin
select * from user;
select * from user where user_name like '王%';
end /
delimiter ;
调用
declare result_varc varchar(10);
call test_proc(1,'李四',result_varc);
函数和存储过程的区别
语法结构不同,存储过程为了返回多个结果集,去掉的返回值,将返回值变成的输出out
参数,而函数必须有返回值,只能接收输入参数。
功能定位不同,存储过程定义为操作特定表的一系列sql的集合,可以返回一个或多个结果集,而函数通常是不涉及特定用户表(有时候用来查询也是可以的),不能返回结果集,只能返回一个变量。
功能定位不同导致的,存储过程支持事务,函数不支持事务,函数中使用commit会报错:Error Code: 1422. Explicit or implicit commit is not allowed in stored function or trigger.
。所以不要使用函数来增删改。
调用方式不同,存储过程一般是作为一个独立的执行语句,而函数可以作为查询语句的一个部分来调用。