史上最简单的 MySQL 教程(四十三)「函数」

温馨提示:本系列博文已经同步到 GitHub,地址为「mysql-tutorial」,欢迎感兴趣的童鞋StarFork,纠错。

函数

函数,就是将一段代码封装到一个结构中,在需要执行该段代码的时候,直接调用该结构(函数)执行即可。此操作,实现了代码的复用。在 MySQL 中,函数有两种,分别为:系统函数和自定义函数。

系统函数

顾名思义,系统函数就是系统定义好的函数,在需要的时候,我们直接调用即可。

任何函数都有返回值(对于空函数,我们就认为其返回值为),而且在 MySQL 中任何有返回值的操作都是通过select来操作的,因此 MySQL 的函数调用就是通过select来实现的。

在 MySQL 中,字符是字符串操作中最常见的基本单位。此外,如果对中文的截取是按字节进行的话,很容易造成乱码的问题。

下面,我们介绍一些常见的、对字符进行操作的系统函数:首先,执行如下语句,定义一些变量,

set @cn = '你好世界';
set @en = 'hello world';
set @one = 'charies';
set @two = 'gavin';
set @three = 'Gavin';

select @cn, @en, @one, @two, @three;
1

然后,调用系统函数进行测试:

  • substring,截取字符串,单位为字符;
2

如上图所示,在 MySQL 中字符串的位置是从1开始,0含有特殊的意义。

  • char_length,获取字符长度;
  • length,获取字节长度;
3
  • instr,判断字符串中某个子串是否存在,存在则返回具体的位置,不存在则返回0
4
  • lpad,左填充,将字符串按照某个指定的填充方式,填充到指定(字符)长度;
5

如上图所示,在对@en进行填充的时候,填充结果为hellohellhello world,其中第二个hello并没有填充全,这是因为系统函数lpad的第二个参数限定的了变量@en的具体长度,如示例中我们设置其为20,而原@en的长度为11,因此只能向@en中在填充9个字符。

  • insert,找到目标位置,将指定长度的字符串替换为目标字符串;
6

如上图所示,insert函数并没有修改变量自身的值,只是对变量的值进行加工而已。

  • strcmp,比较字符串的大小;
7

如上图所示,在用strcmp函数对字符串进行比较的时候不区分大小写(默认校对集),并用0表示两个字符串相等;用-1表示第一个参数的字符串小于第二个参数的字符串;用1表示第一个参数的字符串大于第二个参数的字符串。

自定义函数

对于任意一个函数,其都包含如下要素:

  • 函数名;
  • 参数类别(可以为空);
  • 返回值;
  • 函数体(作用域)。

根据上面这些函数要素,我们就来尝试创建自定义函数。

创建函数

-- 基本语法
create function 函数名([参数列表]) returns 数据类型
begin
	-- 函数体
	-- 返回值,类型为 returns 指定的数据类型
end

如果我们定义的函数的函数体内仅含有返回值,则可以省略beginend。此外,自定义函数和系统函数的调用方式相同。执行如下语句,进行测试:

-- 自定义函数
create function showLove() returns int
return 521;
-- 调用自定义函数
select showLove();
8

查看函数

查看函数,基本语法为:

  • show function status + [like 'pattern'];
9

如上图所示,我们可以看到showLove函数是属于test数据库的,这引出了函数的一个性质,即函数是属于具体数据库的,在一个数据库定义的函数不能在其定义的数据库外使用,但是可以查看

查看函数的创建语句,基本语法为:

  • show create function + 函数名;
10

修改函数 & 删除函数

函数只能先删除后新增,不能修改。删除函数的基本语法为:

  • drop function + 函数名;

执行如下语句,进行测试:

-- 删除函数
drop function showLove;
-- 查看函数
show function status like 'showLove'\G;
11

函数参数

对于函数的参数,一共有两种,分别为形参和实参,其中,形参可以理解为定义函数时使用的参数,且形参必须指定数据类型;实参可以理解为在调用函数时传入的值或变量。因此,函数定义的具体形式应该为:

  • function 函数名(形参名字 形参类型) returns 返回数据类型

下面,我们定义一个函数,完成一个简单的需求,即求1到指定数值的和。代码如下:

delimiter $$
create function addAll(num int) returns int
begin
	-- 定义条件变量
	set @i = 1;
	set @res = 0;    -- 保存求和结果
	-- 循环求和
	while @i <= num do
		-- 任何变量想要修改值都必须使用 set 关键字,且 MySQL 中没有 += 或者 ++ 运算符
		set @res = @res + @i;
		-- 修改循环变量
		set @i = @i + 1;
	end while;
	-- 返回求和结果
	return @res;
end
$$
delimiter ;
12

如上图所示,函数已经定义成功。接下来,执行如下语句,进行测试:

-- 调用函数求和
select addAll(100);

-- 查询自定义变量 @res 和 @i
select @res, @i;
13

如上图所示,求和函数addAll已经正确执行。此外,我们发现在函数内部使用@符号定义的变量@res@i在函数外部也是可以查看使用的,这说明:使用@符号定义的变量为全局变量

变量作用域

在 MySQL 中,变量的作用域有两种,分别为全局和局部,其中,全局变量可以在任何地方使用;局部变量只能在函数内部使用。

  • 全局变量:使用set关键字定义,用@符号标识;
  • 局部变量:使用declare关键字声明,且所用的局部变量必须在函数体开始之前进行声明。

接下来,我们利用局部变量定义一个函数,完成一个简单的需求,即求1到指定数值的和,要求10的倍数不加。代码如下:

delimiter $$
create function addAll2(num int) returns int
begin
	-- 声明变量,包含循环变量和结果变量
	declare i int default 1;    -- 定义局部变量可以含有属性
	declare res int default 0;
	-- 循环求和
	mywhile:while i <= num do
		-- 条件判断
		if i % 10 = 0 then
			-- 修改循环变量
			set i = i + 1;
			-- 重新循环
			iterate mywhile;
		end if;
		-- 修改结果变量
		set res = res + i;
		-- 修改循环变量
		set i = i + 1;
	end while;
	-- 返回求和结果
	return res;
end
$$
delimiter ;
14

如上图所示,函数已经定义成功。接下来,执行如下语句,进行测试:

-- 调用函数求和
select addAll(100), addAll2(100);
15

如上图所示,函数已经正确执行。


温馨提示:符号[]括起来的内容,表示可选项;符号+,则表示连接的意思。


———— ☆☆☆ —— 返回 -> 史上最简单的 MySQL 教程 <- 目录 —— ☆☆☆ ————

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏算法channel

Python|编写自己的类

01 类(对象) class dog(object) 以上定义了一个dog对象,它继承于根类object. 02 类的属性 def __init__(s...

37450
来自专栏思考的代码世界

Python基础学习00天

12730
来自专栏大愚Talk

我对变量产生了这些想法

最近在学习Golang的过程中,发现一个有意思的事情,有的文章说函数调用传参时 slice 是引用传递,有的说是值传递。为什么同一个东西大家会不同认识?为了搞清...

9910
来自专栏前端小栈

转 javascript基础详解-执行环境与作用域链

函数调用都有与之相关的作用域和上下文。从根本上说,范围是基于函数(function-based)而上下文是基于对象(object-based)。换句话说,作用域...

6410
来自专栏吴裕超

ES6之模版字符串

  但是我们可以看到:这样的传统做法需要使用大量的“”(双引号)和 + 来拼接才能得到我们需要的模版。但是这样是十分不方便的。

8310
来自专栏锦小年的博客

python学习笔记6.2-类常见的编程模式

上一次写过一篇有关于python类的博客,现在回头去看看,发现好多语法还是比较低级,表达不是很清晰。现在谈一谈对python类的表达的新的理解。 本篇博客的...

25290
来自专栏LEo的网络日志

python技巧分享(十一)

14540
来自专栏Python小屋

详解Python序列解包

序列解包(Sequence Unpacking)是Python中非常重要和常用的一个功能,可以使用非常简洁的形式完成复杂的功能,大幅度提高了代码的可读性,减少了...

41170
来自专栏从零开始学自动化测试

python笔记22-literal_eval函数处理返回json中的单双引号

在做接口测试的时候,最常见的接口返回数据就是json类型,json类型数据实际上就是字串,通常标准的json格式是可以转化成python里面的对应的数据类型的 ...

22210
来自专栏零基础使用Django2.0.1打造在线教育网站

关于JAVA你必须知道的那些事(二):封装

时隔近一年,我突然想起来这个文章还没有发完,所以就继续开始写。也不知道自己上次写到哪里了,不管了这里从面向对象的三个特性说起。

8810

扫码关注云+社区

领取腾讯云代金券