#创建存储子程序需要CREATE ROUTINE权限。 #· 提醒或移除存储子程序需要ALTER ROUTINE权限。这个权限自动授予子程序的创建者。 #· 执行子程序需要EXECUTE权限。然而,这个权限自动授予子程序的创建者。同样,子程序默认的SQL SECURITY 特征是DEFINER,它允许用该子程序访问数据库的用户与执行子程序联系到一起 #-------------------------------------------------------------------------------------------------------# #mysql函数即使重启mysqld服务后函数依然会存在,只存在指定的数据库,不会跨数据库 drop database if exists test_1; create database test_1; use test_1; drop table if exists test1; #create table test1 (user_id int(11) auto_increment,user_sn int() not null,primary key(user_id)); select year(now()),month(now()),dayofmonth(now()); #年月日 select concat(year(now()),month(now()),dayofmonth(now())); #年月日 create table userorder (userorder_id int(11) auto_increment,primary key(userorder_id),order_sn bigint(15) not null);#用户订单表 #sql自定义函数的总结 delimiter $$ #定义结束符 $$ drop function if exists hello; #判断hello函数是否存在,如果存在则删除 create function test_1.hello (name char(20),age int(2)) returns char(225) #sql 顾名思义 是创建函数的意思 , 注意:语言是强类型语言因此要声明参数的类型 和返回值的类型 begin #函数体的开始 #set @i=0; #声明一个全局变量@i sql也有局部和全局变量 declare greeting char(20); #声明一个局部变量 注意:函数内部不能同时有局部变量和全局变量的存在 declare num int(20); declare str char(20); declare restr char(225); declare max int(20); if hour(now()) < 12 then set greeting ='早上好'; #set 一般用来赋值 赋值给局部变量 全局变量一样 elseif hour(now()) >12 then set greeting ='下午好'; end if; #end if这里一定要分开 if (age < 18) then #判断条件可以加上括号 set str='未成年'; else set str='成年'; end if; set num=0; while num < age do set num=age+1; end while; #注意分开 end while set max =0; w:while age < 100 do set age=age+1; if age = 4 then #leave w; #leave 相当于break 跳出循环 w 是指明关键字leave跳出那个循环的 iterate w; #iterate 相当于continue 跳过循环 end if; set max=max+1; end while w; #select concat(name,greeting,'你的幸运数字是') into restr; select concat(name,greeting,'你的幸运数字是',max,str) into restr; return restr; end $$ delimiter ; select test_1.hello('huangyanxiong',12); #函数调用 #-------------------------------------------------------------------------------------------------------------------------------------# #创建一个自动生成订单序号的函数20140103001 #作用:可以减少连接数据库的次数,减少数据库的负担,加快程序的的运行 drop function if exists create_sn; delimiter $$ create function test_1.create_sn() returns bigint(15) #编写程序时要注意数据类型 begin declare order_sn bigint(15); declare prev bigint(15); declare prevdatetime bigint(15); declare sn bigint(15); declare nowdate bigint(15); select order_sn from userorder order by userorder_id desc limit 1 into prev; #赋值prev select concat(year(prev),month(prev),dayofmonth(prev)) into prevdatetime; select right(prev,4) into sn; select concat(year(now()),month(now()),dayofmonth(now())) into nowdate; #if isnull(prev) && nowdate = prevdatetime then mysql不支持这样写 if isnull(prev) then select concat(nowdate,'0001') into order_sn; return order_sn; elseif nowdate = prevdatetime then select concat(nowdate,'0001') into order_sn; return order_sn; else select concat(prevdatetime,(sn+1)) into order_sn; return order_sn; end if; end $$ delimiter ; select create_sn(); #--------------------------------------------------------------------------------------------------- #产生随机字符串,用于测试数据库 drop function if exists randstr; delimiter $$ create function test_1.randstr(num int(11)) returns char(255) #为了容易区分那个函数或者存储过程是那个数据库的,可以在函数名中加上数据库前缀test_randstr; begin declare str char(255) default 'q1we23r4t5y6u7i8o9p0asdfghjklzxcvbnm'; declare nums int(11); declare returnstr char(255); #SQL变量名不能和列名一样 declare i int(11) default 0; #在声明变量时一定要在begin语句之后,除begin外的任何语句之前 select floor(truncate(rand(),1)*36)+1 into nums; #加1时为了防止产生随机数生成0的情况 select substring(str,nums,1) into returnstr; #declare i int(11) default 0; #在声明变量时一定要在begin语句之后,除begin外的任何语句之前,像这个语句是不允许的 while i <num do select floor(truncate(rand(),1)*36)+1 into nums; select concat(substring(str,nums,1),returnstr) into returnstr; #set returnstr=concat(substring(str,nums,1),returnstr); set i=i+1; end while; return returnstr; end $$ delimiter ; #-----------------------------------------------------------------------------------------------------------------------# show function status like '%rand%'; #查看函数的状态 包括:函数所属数据库,函数名,类型,创建时间,创建者,安全类型 注释 ,数据库字符集,客户端字符集 show procedure status like '%procedure_name'; #同上 #------------------------------------------------------------------------------------------------------------------------------# insert into userorder values(null,test_1.create_sn()); #-------------------------------------------------------------------------------------------------------------------------------------# drop function if exists ceshi; delimiter $$ create function ceshi() returns char(255) begin declare ceshistr1 char(255); declare ceshistr2 char(255); declare ceshistr char(255); #select order_sn,userorder_id from userorder limit 1 into ceshistr; #ERROR 1222 (21000): The used SELECT statements have a different number of columns select order_sn,userorder_id into ceshistr1,ceshistr2 from userorder limit 1 ; #在mysql中一个列的数据必须占用一个变量,否则会出现上面的错误 select concat(ceshistr1,ceshistr2) into ceshistr; #select * from userorder; #存储函数的限制:不能再存储函数中返回整个表的数据ERROR 1415 (0A000): Not allowed to return a result set from a function return ceshistr; #而存储过程可以返回整张表的数据 end $$ delimiter ; #-------------------------------------------------------------------------------------------------------------------------------------------# drop procedure if exists simpleproc; delimiter $$ CREATE PROCEDURE simpleproc (OUT param1 INT) BEGIN SELECT * FROM userorder; #而存储过程可以返回整张表的数据 END $$ delimiter ; call simpleproc(); #调用存储过程 #--------------------------------------------------------------------------------------- drop procedure if exists pr_param_in; delimiter $$ create procedure pr_param_in ( in id int) begin if (id is not null) then set id = id + 1; end if; select id as id_inner; end; $$ delimiter ; #----------------------------------------------------------------------------------------------------------------------------------------------------# #----------------------------------------------------------------------------------------------------------------------# #第一个自己的存储过程 drop procedure if exists test; #判断一个存储过程是否存在存在则删除 delimiter $$ create procedure test () begin select 'hello world!' as helloworld; end; $$ delimiter ; call test(); #--------------------------------------------------------------------------------------------------------# #存储过程学习声明变量 drop procedure if exists test2; delimiter $$ create procedure test2 () begin declare str char(255) default 'huangyanxiong'; #在存储过程声明局部变量并赋值 set @color='red'; #在存储过程中声明全局变量并赋值, 注意:函数内不能同时有局部变量和全局变量 #select * from userorder; select @color as colors; #一般采用这种方式输出到终端 end $$ delimiter ; call test2(); #--------------------------------------------------------------------------------------# #存储过程传递参数 drop procedure if exists test3; delimiter $$ create procedure test3(in username char(50)) begin select username as user_name; end $$ delimiter ; call test3('huangyanxiong'); drop procedure if exists test4; delimiter $$ #----------------------------------------------------------------------------------# create procedure test4(username char(50)) begin declare str char(50); select concat(username,'xxxxxx') into str; select str as string; #设置别名返回 #select 'dds' as d; #return strs; # ERROR 1313 (42000): RETURN is only allowed in a FUNCTION return 语句只能在函数中使用 end; $$ delimiter ; call test4('huangyanxiong'); #------------------------------------------------------------------------------------# drop procedure if exists test5; delimiter $$ create procedure test5 (username char(50)) #默认使用in begin set @age=12; select username as usernames,@age as age; #使用同一张表返回 end $$ delimiter ; call test5('huangyanxiong'); #-------------------------------------------------------------------------------------# #把函数改变为存储过程很简单,把函数改改就可以 #把上面的订单序号改为存储过程 drop procedure if exists create_sn; delimiter $$ create procedure create_sn() begin declare order_sn bigint(15); declare prev bigint(15); declare prevdatetime bigint(15); declare sn bigint(15); declare nowdate bigint(15); select order_sn into prev from userorder order by userorder_id desc limit 1 ; #赋值prev SELECT prev; select concat(year(prev),month(prev),dayofmonth(prev)) into prevdatetime; select right(prev,4) into sn; select concat(year(now()),month(now()),dayofmonth(now())) into nowdate; #if isnull(prev) && nowdate = prevdatetime then mysql不支持这样写 if isnull(prev) then select concat(nowdate,'0001') into order_sn; select order_sn as ordersn; elseif nowdate != prevdatetime then select concat(nowdate,'00011') into order_sn; select order_sn as ordersn; else select concat(prevdatetime,(sn+1)) into order_sn; select order_sn as ordersn; end if; end $$ delimiter ; select * from userorder; call create_sn(); #-------------------------------------------------------------------------------# #产生随机字符串,用于测试数据库 drop procedure if exists randstr; delimiter $$ create procedure randstr(num int(11)) #为了容易区分那个函数或者存储过程是那个数据库的,可以在函数名中加上数据库前缀test_randstr; begin declare str char(255) default 'q1we23r4t5y6u7i8o9p0asdfghjklzxcvbnm'; declare nums int(11); declare returnstr char(255); #SQL变量名不能和列名一样 declare i int(11) default 0; #在声明变量时一定要在begin语句之后,除begin外的任何语句之前 select floor(truncate(rand(),1)*36)+1 into nums; #加1时为了防止产生随机数生成0的情况 select substring(str,nums,1) into returnstr; #declare i int(11) default 0; #在声明变量时一定要在begin语句之后,除begin外的任何语句之前,像这个语句是不允许的 while i <num do select floor(truncate(rand(),1)*36)+1 into nums; select concat(substring(str,nums,1),returnstr) into returnstr; #set returnstr=concat(substring(str,nums,1),returnstr); set i=i+1; end while; select returnstr as randstr; end $$ delimiter ; call randstr(5); #----------------------------------------------------------------------#