知识点:
- 自定义函数定义
- 创建、调用、删除自定义函数
- 自定义函数的应用
- 深入自定义函数
- 复合结构
- 局部变量的创建、赋值;全局变量的创建
- 流程控制语句:条件语句(if、case)、控制循序条件语句(leave跳出循环、iterate跳出当前循环)、循环语句(loop、repeat、while)
一.定义
用户自定义函数(user-defined function,UDF)是一种对MySQL扩展的途经,其用法与内置函数相同。
二.创建、修改、删除自定义函数
1.创建自定义函数:无参自定义函数、有参自定义函数
创建UDF:
CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,[parameter_name type,...])
RETURNS {STRING|INTEGER|REAL}
runtime_body
简单来说就是:
CREATE FUNCTION 函数名称(参数列表)
RETURNS 返回值类型
函数体
解析:
returns后面的为返回值类型,return后面的为返回值。
自定义函数有两个必要条件:
- 参数
- 返回值:return后面的为返回值
函数可以返回任意类型的值,同样可以接收这些类型的参数。
函数的参数和返回值之间没有必然的内在的联系。
关于函数体
- 函数体由合法的sql语句构成;
- 函数体可以是简单的SELECT或INSERT语句;
- 函数体如果为复合结构(多个语句要执行)则使用BEGIN…END语句;
- 复合结构可以包含声明,循环,控制结构;
注意:
1.如果在创建函数的时候遇到you *might* want to use the less safe log_bin_trust_function_creators variable
需要执行 :SET GLOBAL log_bin_trust_function_creators = 1;
2.在输入要执行的sql语句后,后面的分号为当前默认的分隔符,导致函数无法再继续输入。因此需要修改默认的分隔符。
需要执行:delimiter $$ #修改默认的结束符";"为"$$",以后的SQL语句都要以"$$"作为结尾
例1:创建无参自定义函数:返回当前时间的,年月日 时分秒。
第一种:
delimiter$$ #将默认的结束符";"修改为"$$"
create function f1()
returns datetime
begin
return now();
end$$
delimiter; #改回;
第二种:
delimiter$$
create function f1()
returns datetime
return now()$$
delimiter;
例2:创建有参自定义函数:求两个数的平均值。
DELIMITER$$
CREATE FUNCTION f2(num1 SMALLINT UNSIGNED, num2 SMALLINT UNSIGNED)
RETURNS FLOAT(10,2) UNSIGNED
RETURN (num1+num2)/2$$
DELIMITER;
例3:创建具有复合结构函数体的自定义函数:创建一个函数向表中插入数据,并返回所插入数据的id。
DELIMITER$$
CREATE FUNCTION f4()
RETURNS INT(10) UNSIGNED
BEGIN
INSERT INTO goods(goods_name,goods_num) VALUES('圆珠笔',10);
RETURN LAST_INSERT_ID();
END$$
DELIMITER;
2.调用自定义函数语法:(和使用内置函数一样,使用它)
SELECT function_name(parameter_value,...);
3.删除自定义函数语法:
drop function [IF EXISTS] function_name;
三.自定义函数的应用
四.深入使用自定义函数
1.复合结构
参考例3
2.局部变量和全局变量
自定义函数中定义局部变量语法:
DECLARE var_name[,varname]...date_type [DEFAULT VALUE];
简单来说就是:
DECLARE 变量1[,变量2,... ]变量类型 [DEFAULT 默认值];
这些变量的作用范围是在BEGIN...END程序中,而且定义局部变量语句必须在BEGIN...END的第一行定义
示例:
DELIMITER $$
CREATE FUNCTION addTwoNumber(x SMALLINT UNSIGNED, Y SMALLINT UNSIGNED)
RETURNS SMALLINT
BEGIN
DECLARE a, b SMALLINT UNSIGNED DEFAULT 10;
SET a = x, b = y;
RETURN a+b;
END$$
上边的代码只是把两个数相加,当然,没有必要这么写,只是说明局部变量的用法,还是要说明下:这些局部变量的作用范围是在BEGIN...END程序中
变量赋值语法:
SET parameter_name = value[,parameter_name = value...]
SELECT INTO parameter_name
例:
...在某个UDF中...
DECLARE x int;
SELECT COUNT(id) FROM tdb_name INTO x;
RETURN x;
END$$
用户变量定义语法:(可以理解成全局变量)
SET @param_name = value
例:
SET @allParam = 100;
SELECT @allParam;
上述定义并显示@allParam用户变量,其作用域只为当前用户的客户端有效
3.自定义函数中流程控制语句语法:
存储过程和函数中可以使用流程控制来控制语句的执行。
MySQL中可以使用IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句和WHILE语句来进行流程控制。
每个流程中可能包含一个单独语句,或者是使用BEGIN...END构造的复合语句,构造可以被嵌套。
1.IF语句
IF语句用来进行条件判断。根据是否满足条件,将执行不同的语句。其语法的基本形式如下:
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
解析:
其中,search_condition参数表示条件判断语句;statement_list参数表示不同条件的执行语句。
注意:MYSQL还有一个IF()函数,他不同于这里描述的IF语句
例题:
例1:根据输入的参数来判断age与18,20的关系来确定是不是成年人
DELIMITER$$
CREATE FUNCTION f1(age int(10))
RETURNS varchar(255)
BEGIN
IF age<18 THEN return '未成年人';
ELSEIF age=20 THEN return '20岁了';
ELSE return '成年人';
END IF; #IF语句都需要使用END IF来结束。
END$$
DELIMITER;
->select f1(10);
结果为:未成年人
例2:根据输入的工资来涨工资
delimiter$$
create function f2(salary int(10))
returns int(10)
begin
declare aaa int(10) default 0; #同样可以使用局部变量和全局变量
if salary<=3000 then return salary+500; #工资不高于3000,涨500
elseif 3000<salary<=5000 then return salary+1000; #工资大于3000而不高于5000,涨1000
else return salary+2000; #工资高于5000,涨2000
end if;
end$$
delimiter;
IF语句都需要使用END IF来结束。
IF函数:
语法:IF(value,t,f)函数
例:
select if((age)<18,'未成年人','成年人') from table_test;
解析:查询table_test表中的age列,如果age<18,则返回‘未成年人’,否认返回‘成年人’;
IFnull函数:
IFNULL(value1,value2)函数
例:select ifnull(salary,0) from table_test;
解析:查询table_test表中的salary列,如果为null,则返回0
2.CASE语句(有两种格式)
CASE语句也用来进行条件判断,其可以实现比IF语句更复杂的条件判断。CASE语句的基本形式如下:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
解析:
其中,case_value参数表示条件判断的变量;
when_value参数表示变量的取值;
statement_list参数表示不同when_value值的执行语句。
例:
delimiter$$
create function f1(damage int(10))
returns varchar(255)
begin
case damage
when 100 then return 'adc';
when 90 then return 'ad';
when 65 then return '坦克';
else return 'ap';
end case; #CASE语句都要使用END CASE结束
end$$
delimiter;
CASE语句还有另一种形式。该形式的语法如下:
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
解析:
其中,search_condition参数表示条件判断语句;
statement_list参数表示不同条件的执行语句。
例:
delimiter$$
create function f1(damage int(10))
returns varchar(255)
begin
case
when damage=100 then return 'adc';
when damage=90 then return 'ad';
when damage=65 then return '坦克';
else return 'ap';
end case; #CASE语句都要使用END CASE结束
end$$
delimiter;
下面是一个CASE语句的示例。代码如下:
CASE age
WHEN 20 THEN SET @count1=@count1+1;
ELSE SET @count2=@count2+1;
END CASE ;
代码也可以是下面的形式:
CASE
WHEN age=20 THEN SET @count1=@count1+1;
ELSE SET @count2=@count2+1;
END CASE ;
本示例中,如果age值为20,count1的值加1;否则count2的值加1。CASE语句都要使用END CASE结束。
注意:这里的CASE语句和“控制流程函数”里描述的SQL CASE表达式的CASE语句有轻微不同。这里的CASE语句不能有ELSE NULL子句
并且用END CASE替代END来终止!!
case表达式:
第一种:
SELECT id,CASE
WHEN damage<=60 THEN 'ap'
WHEN damage<80 THEN 'ad'
WHEN damage>80 THEN'adc'
ELSE 0
END
FROM test3;
第二种:
SELECT id,CASE damage
WHEN 70 THEN 'ap'
WHEN 85 THEN 'ad'
WHEN 100 THEN'adc'
ELSE 0
END
FROM test3;
3.LOOP语句
LOOP语句可以使某些特定的语句重复执行,实现一个简单的循环。
但是LOOP语句本身没有停止循环的语句,必须是遇到LEAVE语句等才能停止循环。
LOOP语句的语法的基本形式如下:
[begin_label:] LOOP
statement_list
END LOOP [end_label]
解析:
其中,begin_label参数和end_label参数分别表示循环开始和结束的标志,这两个标志必须相同,而且都可以省略;
statement_list参数表示需要循环执行的语句。
下面是一个LOOP语句的示例:从1加到无穷,因为没有条件结束循环。代码如下:
DELIMITER$$
CREATE FUNCTION f3()
RETURNS INT(10)
BEGIN
DECLARE x INT(10);
declare y int(10);
SET X=0;
set y=1;
-- 开始循环
LOOP
SET x=x+y;
set y=y+1;
END LOOP ; -- 结束循环
RETURN X;
END$$
DELIMITER;
结果:
会一直执行,因为没有结束循环的条件
该示例循环执行1到无穷的操作。因为没有跳出循环的语句,这个循环成了一个死循环。
LOOP循环都以END LOOP结束。
4.LEAVE语句
LEAVE语句主要用于跳出循环控制。其语法形式如下:
LEAVE label
解析:
其中,label参数表示循环的标志。
例1:从1加到99,代码如下
DELIMITER$$
CREATE FUNCTION f5()
RETURNS INT(10)
BEGIN
DECLARE X INT(10);
DECLARE Y INT(10);
SET X=0;
SET Y=1;
-- 开始循环
myloop:LOOP
SET X=X+Y;
SET Y=Y+1;
IF Y=100 THEN LEAVE myloop;
END IF; --记得结束if语句
END LOOP myloop; -- 结束循环
RETURN X;
END$$
DELIMITER;
5.iterate 语句
ITERATE语句也是用来跳出循环的语句。但是,ITERATE语句是跳出本次循环,然后直接进入下一次循环。
ITERATE语句只可以出现在LOOP、REPEAT、WHILE语句内。
ITERATE语句的基本语法形式如下:
ITERATE label
其中,label参数表示循环的标志。
例子:从1加到99,但是不加2,代码如下
DELIMITER$$
CREATE FUNCTION f5()
RETURNS INT(10)
BEGIN
DECLARE X INT(10);
DECLARE Y INT(10);
SET X=0;
SET Y=1;
-- 开始循环
myloop:LOOP
SET X=X+Y;
SET Y=Y+1;
IF Y=2 THEN ITERATE myloop;
END IF; --如果是if语句,记得结束if语句
IF Y=100 THEN LEAVE myloop;
END IF; --如果是if语句,记得结束if语句
END LOOP myloop; -- 结束循环
RETURN X;
END$$
DELIMITER;
说明:LEAVE语句和ITERATE语句都用来跳出循环语句,但两者的功能是不一样的。
LEAVE语句是跳出整个循环,然后执行循环后面的程序。而ITERATE语句是跳出本次循环,然后进入下一次循环。
使用这两个语句时一定要区分清楚。
6.repeat 语句
REPEAT语句是有条件控制的循环语句。当满足特定条件时,就会跳出循环语句。REPEAT语句的基本语法形式如下:
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
其中,statement_list参数表示循环的执行语句;search_condition参数表示结束循环的条件,满足该条件时循环结束。
下面是一个REPEAT语句的示例。代码如下:
delimiter$$
create function f6()
returns int(10)
begin
declare x int(10);
declare y int(10);
set x=0;
set y=1;
--开始循环
repeat
set x=x+y; --不要忘记加set
set y=y+1;
until y=101
end repeat; --结束循环
return x; --不要忘记return
end$$
delimiter;
该示例循环执行从1加到100,y值为101时结束循环。
REPEAT循环都用END REPEAT结束。
7.WHILE语句
WHILE语句也是有条件控制的循环语句。但WHILE语句和REPEAT语句是不一样的。
WHILE语句是当满足条件时,执行循环内的语句。
WHILE语句的基本语法形式如下:
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
其中,search_condition参数表示循环执行的条件,满足该条件时循环执行;
statement_list参数表示循环的执行语句。
下面是一个ITERATE语句的示例。代码如下:
例1:
DELIMITER$$
CREATE FUNCTION f11()
RETURNS INT(10)
BEGIN
DECLARE X INT(10);
SET X=1;
-- 开始循环
WHILE X<100
DO
SET X=X+1;
END WHILE ; -- 结束循环
RETURN X;
END$$
DELIMITER;
例2:
DELIMITER$$
CREATE FUNCTION f7(a INT)
RETURNS VARCHAR (255)
BEGIN
DECLARE X INT;
DECLARE Y INT;
SET Y = a;
-- 开始循环
WHILE Y < 10 DO
SET Y = Y + 1;
END WHILE; -- 结束循环
RETURN Y;
END$$
DELIMITER;
该示例循环执行count加1的操作,count值小于100时执行循环。
如果count值等于100了,则跳出循环。WHILE循环需要使用END WHILE来结束。