00:00
接着啊,咱们来学习一下这个存储函数,存储函数的话呢,实际上呢,就是我们用户自定义的函数,那前面的话呢,咱们其实已经接触了很多的函数了,对吧?系统给我们提供的这个单行函数啊,我们看了好多类别呢,给大家去讲解,然后呢,也讲了这种聚合函数,那当然了,我们使用这些函数的话呢,是不是在开发过程当中就很方便了,极大的提高了我们对数据库的一个管理的效率,对吧?那么我们自己去定义函数呢,那同样的道理也能够提高我们对数据库啊操作的一个效率问题,那这属于它的一个好处。OK,那具体调用的话呢,跟咱们前面调用这个,呃,预定义的一些系统函数呢是一样的,我们直接使用select加上这个函数呢就可以了。那就可以了,行,那下边呢,我们来看一看咱们函数的一个定义的语法。定律语法跟我们前面讲的这个存储过程啊,也会有一些不同,那也会有些不同,好,那我们来看一下这里呢,我们叫create function,哎,创建一个函数,那我们这呢,那就是how to how to create function,那就是create function,就是咱们在整个搜当中呢,大家应该发现这个套路了,你想创建什么呢?你是不是就这块儿呢,写创建什么就可以了。
01:10
OK,然后后边呢,就紧跟着是我们这个函数名,然后呢参数名参数类型,注意跟我们存储过程有一个很大的区别,就是我们一定在下边儿呢,要带一个叫returns,然后反应类型。那这呢,就能看到我们这个函数啊,它是一定有返回值类型的,对吧?诶,OK,然后再往下的话呢,叫characteristic,这个呢,我们称为呢叫特征,或者你叫约束也行,就是来限制我们这个函数啊,或者对我们这函数呢做一定的描述的这样的一些特征值,OK,然后再往下的话呢,叫做begin和end,那对应的里边呢,叫函数题,叫函数题,由于呢,我们说函数呢,是一定会有返回值的,所以呢,我们在这个函数题里边呢,一定会去写这个return这样的一个关键字,就是表示呢,我们这函数执行完以后呢,它到底要返回一个什么,这个返回的内容呢,我们实际上呢,是不是可以作为我们select查询的一个东西啊。
02:04
嗯,查询的东西出现,就好比是呢,我们原来的时候呢,比如说咱们做一个这个四舍五入,咱们用的叫round是吧,诶123.45。那这个呢,我们就不写这个逗号几了,那这块呢,其实就是对整数位进行一个45了,123.45的话呢,然后呢,它相当于返回的不就是你这个数的一个整数位吗?就是123对吧?OK,行,就相当于函数呢,它是一定会有返回值的啊,这个我再强调一遍,然后呢,我们对上面这描述的话呢,首先来来看到这个叫参数列表,这个呢,根据实际情况的需要,有多个呢就写多个啊,有一个呢就写一个,没有呢就可以不写。但是呢,你要注意就是我们这时候这个参数呢,跟存储过程的区别在于存储过程呢,它有几种类型,有in,有out,有in outt,当然对于我们函数来讲呢,咱们就只有啊是印类型的,相对呢,它只是充当了是不是叫呃入参,或者我们叫这个自变量。能理解吧?就是比如说这个呢,是我们这个函数还是回归到咱们上这个中学的时候,大家学的这个函数,然后这个位置呢,我们学的这个存进去的叫自变量,然后经过这个函数以后呢,出来的叫因变量,对吧?GX呢,你可以理解成是一个自变量,那如果我用这个大写的X表示呢,它其实可以是一个向量的,然后X1 x21直到XN是吧?可以用N个自变量,但是出来的这个呢,永远都只有一个变量。
03:22
哎,都只有这一个变量啊,这个大家要注意一下,呃,那么这里边呢,就相当于是我们这个形态位置呢,只能够填这个自变量了,所以它永远都只是in类型的,但是这印呢,就不用写了。啊,不用写为因啊,就直接写变量就行,你理解为in,然后第二的话呢,就是returns type,这个呢,就是明确的就是返回值的一个类型,嗯,然后呢,这个是强制需要写的,而且对应里边的这个return,嗯,Return,你返回的这个变量也好,这个表达式也好,它的类型跟我们这个类型呢,要匹配的上,对吧,要一致啊就这个反馈的是一个数据,这个呢,是对应的这个数据对应的类型。然后这个characteristic呢,跟咱们前面讲的啊,存储过程里边,对这个存储过程这个约束呢,是完全一样的。
04:06
是完全一样的,那简单的我们再稍微再看一下,比如说有哪些啊。啊提到了我们整个呢,这里边啊执行体那都是由这个circleq语句构成的,那这呢叫language circle,还有呢,这个呢是说你这个函数的执行结果是,呃我们我们现在说的是函数了啊哎,你这个函数的执行结果呢,是不是确定的,呃,你比如说同样的这个输入数据,每次执行完以后呢,输入的结果是不是相同的啊这个呢,相同呢就是呃determine,呃determine是吧,那你要不相同的话呢,就是加个not就可以了,然后接下来的话呢,指明我们当前你这个呃子程序呢,你是包含circleq的还是不包含SQ的,还是说呢,它是这个读数据的还是是写数据的。啊这个意思,然后下边呢,就是你这个,呃,当前定义好的,比如我们这个函数啊,这个函数你是只能是定义者去使用,还是说呢,只要有权限的调用者也可以去用,就是它涉及到一个调用的一个权限问题,然后这块呢,就我们注释信息对吧,那其实也比较简单,那这些呢,我们都可以统称为呢叫啊characteristic啊对吧。
05:08
好,然后这个比跟N的这块呢,大家正常呢,你看你函数要做什么啊,就是写就完了对吧?啊接着里边呢,一定有一个return,下面的话呢,就是我们这个一个调用了,当我们创建好以后呢,它的调用呢,就是使用的叫select。前面的存储过程咱们用的是什么呀。还记得吧?是不是这个扣啊啊OK啊行,然后接下来的话呢,就是关于我们这个存储函数的一些举例了,那咱们就一个一个的来写一写,好这块我们拉过来啊,这呢是我们讲的第二个叫存储函数,OK。行,来,我们就做一做这个练习题。哎,这样我把它就放到这一行上去了。嗯,把这个呢,我们再换一下啊。好,那这里边呢,我们有几个练习题啊,通过练习题呢,咱们去熟悉一下这个存储函数,它的一个,呃,这个声明情况说呢,创建一个存储函数,然后名称为它,哎跟咱们讲一个存储过程有一点也是一样的,上来呢,咱们是不是个deter啊,诶把它写上OK,然后最后的话呢,你在诶deter,然后呢,诶把这个符号呢再收起来,在这个呢,我们就直接呢去create。
06:15
嗯,Function是吧,创建具体的这个函数,函数名呢,这个我们起好了已经,那就放到这儿。叫email by name。Email by name行那个定义参数呢是空的,那这里边就不用写了,那下边呢,我们是不是针对我们说函数来讲有个returns。说呢该函数查询啊贝尔的email,那email呢,我们说这个邮箱了,是一个字符串类型,所以这块返回的就是一个我串类型,对吧,那这个呢,我们也要写上它的一个范围,那就这样,呃,然后再往下的话呢,我们再要写该写啥了呀。啊,同学说该写这个begin n n了是吧?End,我们先写好这个begin end之前呢,咱们说实际上还可以写上咱们的一些叫characteristic啊,叫约束也行,叫做这个呃,一些特征也可以,就我们刚才呢,带大家过的那一些这个情况是吧,那暂时呢,如果说我们就不写了啊,如果你要不写的话呢,我们直接呢,是不是就begin来写里边这个这个函数题了。
07:10
那这个函数体呢,我们还要做什么?他要查询阿的这个email啊,并返回,OK,那这呢,我们就相当于是做一个select,对吧?Select email,嗯,阿贝尔的email,那就是email。From employees这个呢,咱们使用的还是咱们这个DB t15,然后这个表呢,咱们不是从这个艾硅谷DB这里边复制了两个这个表数据对吧,过来的,好,这时候我们查到呢,就是相当于是这个表了。那where加上一个where where什么呢?这个last name呢?等于叫are there。没问题吧,行,这个呢,就是咱们查询的这样的一条语句,大家应该都比较熟了,我们需要呢,把这个结果呢,是不是给返回啊,那我们只需要在这写个return。是吧,哎,这样就可以了,后边呢,我们补一对这个小括号啊,一个分号结束啊就OK了。
08:00
那就OK了,哎,这个呢,就是咱们写的当前这个函数。那咱们没有包括这个具体的characteristic是吧?哎,就这个特征行,那这时候我们选中之后呢,咱们去执行看看对不对呀,走一下。好,大家发现呢,我们这时候呢,是不是报错了呀,说呢,你这个函数呢,没有这个,呃这个呢,你看就是我们这个determine,呃就是我们这个特征里边的啊呃,Determine这那说你是不是确定的,还有呢,你包完circle,你是这个,呃这个读数据的吗?读circle数据吗?还是写呀,是吧,你这块你都没有说啊说你需要呢去使用啊less。这个这个safe啊,这样的一个参数。啊,这样一个变量,哎等等,那什么意思啊,那这块呢,其实是大家如果去运行的话呢,也会出现这样的问题,那这样问题怎么去解决呢?我在下边儿呢,特意写出来了。哎,大家去注意一下,就是刚才呢,我们不就报这样的问题了吗?是吧,那该怎么去解决呢?在解决方法有两种啊,第一个呢,就是他这里边提到了,说你这里边没有包含这样的一些参数吧。
09:04
那没有包含这样一个参数,那我们就需要呢,考虑上说你到底是不是确定性的,那包不包含circleq啊,还是不包括呀,还说你是这个读这个circleq数据的呀,还是写SQL数据啊,就是把这个呢,你得告诉我。啊告诉我,哎,举个例子啊,你比如说我们这里边呢,咱们就哎注意是在这个returns后边这块去加上我们这些特性的啊,哎这么着这个呢,就相当于是你这个函数这个确定性的是吧,它是个确定性的,然后呢,我们里边呢,是不是包含这个具体的circle啊,哎叫contains circle。啊,是包含的。哎,是包含色库的,然后呢,我们可以呢,去读这个SQ中的这个,呃,数据是吧。哎,我们是这样的的,好,这呢,我们就相当于是加了这这样几个算是这个特性啊,那这样加完以后的话呢,诶我们这时候呢,再去选中呢,做一个执行走起。好,大家看这个时候呢,是不是就不报错了呀,哎,就不报错了,这呢就属于咱们解决的方式一,就是你把这个特性加上呢,它就不报错了,咱们前面讲函数的时候呢,要没加他都,哎讲这个存储过程的时候呢,没有加他倒没有报错是吧?哎,这是它的一个区别,然后第二种处理方式呢,就是他又提到了,说你可以呢去使用这样的一个参数啊,其实这就是个变量了,那我们呢,就把这个变量的值呢,设置为一啊,此时的话呢,它就不会再给我们报错了,这样的话,你就不用用这个方式一,每次去加这样的一些特性。
10:24
哎,就是我们说的两种方式,好,那么此时的话呢,我这里选择了使用相当于第一种方式来进行处理的,对吧,我们加上了这几个呗。OK吧,行,那就加上了啊嗯,那这样的话呢,我们选中以后呢,我也做了一个执行,你看这块呢,有没有报错啊,相当于我们这个函数呢,就创建好了,那函数创建好下一个问题是不是涉及到它的一个调用问题啊来我们怎么调呢?跟以前一样,就用的这个select来调就行,那叫email。哎,BY,诶,Name,哎,就这样就可以了,那此时呢,我们选中去执行,他查询到的是阿贝尔的这个email,来,我们走起。那查出来了,就是他。
11:01
哎,就是这个,那你要说这个担心的话呢,我们是不是可以自己再去写个select对吧,这个email,然后呢,来一个这个,诶,Last nameme from employees where。Lastname等于。阿贝尔。OK,没问题吧,来我们此时呢,把它选中,哎执行一下,你看就是这个有效,那所以我们这里边呢,是没有问题的。OK,这个呢,就是咱们做的这个练习的第一个啊,然后接着我们再看一下第二个。哎,这个。好,我们看这个。嗯。说呢,创建这个存储函数,然后名称呢,是它传入这个参数呢,是这个,然后这样的一个处理行,那这时候呢,我们创建的话呢,整体的套路跟上面一样啊limit。那这个然后呢是双斜线是吧,然后the limit,然后呢,我们再还原回来,诶这里边呢,我们去create。
12:04
哎,Function啊,把这个函数名呢,我们粘过来,Email by ID,哎,整个CTRLC啊粘过来,哎这样,哎有这块了,行,然后传入参数,哎,我们第一个呢是没有参数的,然后这个呢是有参数了,这个参数呢,注意咱们说跟嗯存储过程相比呢,它们全是in是吧,但是这里边你就不用去写这个in了,直接呢写这个,哎这个变量就行,然后它是一个int类型的,没问题。然后这呢,是不是叫returns,嗯,然后呢,我们返回的是什么呀?说该函数查询这个对应ID,它的一个email,那返回的是不是也是一个字串啊,哎,是一个我差类型的,然后这样子。OK的是吧,然后再往下的话呢,我们该写啥了呢?呃,是不是跟上边同样的问题,就是呃,我们得考虑写这样的一个特征对吧?哎,要不的话呢,可能会这个报错哈,那要不想写的话呢,我就想写这个上来了就来这个begin了啊最后这个end呢去收尾,那怎么办呀,咱们刚才提到了第二种处理方案,是不我们就可以呢,加上这样的一个,诶声明吧,哎,CTRLC一下,那这里边咱们把这个。
13:07
哎,在咱们创建这个函数之前。在这写一下。哎,创建函数前。啊,执行词语句。哎,保证呢。保证啊。哎,我们函数的这个创建呢,会成功。OK。啊,就相当于它默认的这个参数的,它这个值呢是个零,然后呢,就不让我们这块去创建,就必须呢,你去告诉我,你这里边儿的一些特征是什么,那要么呢,就是你加上特征,要么呢你就把它改成一,它就不让你去检验这个特征了,OK,这个呢是咱们这个生命函数。OK啊。行,那我们把这个呢,选中咱们做一个执行,哎可以了,然后接下来呢,我们就不去加这些特征了,来下边我们看一下这里边儿怎么写,那它这里呢,是需要查询指定的这个ID,它对应的email啊,那就直接呢,是不是就是select。啊,这个email。
14:01
哎,From一下我们employees是吧,然后where呢叫employee ID呢,是不是等于这个EPID,那就整个这样,然后我们把它呢,作为一个返回值呢,是不是返回啊哎,去做个return,哎这样就可以了。哎,这样就可以了,行,然后呢,我们把它呢,整体选中呢,咱们做一个执行。哎,你看就可以了,然后下边呢调用。哎,调用我们这个函数select。所以like,然后是不是就这个诶粘过来,然后找指定ID的这个员工,他的email是多少,比如我们传个100。哎,传100,看看他的这个邮箱是多少,哎,就是这个啊,传个101。那就这个行,那就这样就可以了,嗯,或者的话呢,咱们还有一种调用方式呢,就是我可以呢select啊还是写上咱们这个函数名。诶,然后这个位置呢,我们写的相当于不是一个常量了,你呢传一个变量的方式也行,那这呢我就用这个set了啊,咱们下一章呢,给大家去专门讲这个变量的这种定义啊,在这块呢,我们可以先写一个,比如我们就叫EPID啊这种复刻值呢,就是102吧。
15:08
哎,这样,然后呢,你把这个变量呢,啊CTRLC咱们放到这,相当于去使用这个变量也可以来,我们选中了执行一下,这个就是102这个人的email。啊,也是OK的啊,这个大家稍微关注一下啊,你要用这个冒号等于也行来,我们选中了直行啊还是它。好,这个呢是咱们举的一个例子,然后接下来我们再看这个举例三。哎,再回过来啊,找到我们这边。比例三,这个好,我们CTRLC。哎,站过来,哎,大家呢,有没有觉得说这函数创建还可以,不太难是吧?哎,不太难啊呃,尤其呢,当你怎么着啊,你接触过上边存储过程了啊,乃至于时候呢,你接触过其他的这个编程语言呢,其实大家呢,就会慢慢的有这种触类旁通的感觉。啊,就是说你会了这个函数的定义之后呢,你在学习其他的这个语言当中,叫方法也好,叫函数也好,那可能它的定义的语法格式呢,都不太一样,但基本上你告诉你那个格式长什么样子以后呢,你就照猫话术的,你就按照它那个套路往里边去套,呃,实际上就都能写出来,咱们现在写这个存储过程也好,存储函数也好,实际上呢,这里边的难度比较大的在哪呢?是不是还是你这个函数体或者叫存储过程体怎么去写呀?
16:22
啊,这里边儿呢,其实融合的还是咱们前面讲过的,是不是一些circle的一些写法呀,哎,所以这个呢是更重要的啊,至于说像前面这些所谓的一些这种描述啊,这个跟你一说你就记住了啊,如果大家比如说你学过Java的话呢,相当于呢,就是咱们接触的像像像这些。像这些是吧,这些呢,格式化的东西呢,就好比是我们在这个使用一个声明一个方法的时候呢,这个方法的这个声明这块一样,然后也是一个小括号,一个大括号,然后这呢,就是告诉你说这里边什么意思,什么意思可以用什么替换是吧?哎,跟这个一样的,然后呢,关键呢,我们这个函数大家能不能写出来还是得看,哎从Java的角度来讲,就是你这个方法体能不能写出来,就类似于我们这个函数里边的这个begin和N的中间这个一样。
17:06
这个代码量比较大,决定了你这个函数或者是存储过程到底是干什么的,这个才是核心,而这个呢,哎,又涉及到了咱们以前讲过的那些circle了。是这意思是吧。好,那回来我们再看一下这个。说创建存储函数是它,哎,还是这个套路,咱们先把前面这个给该加的加上啊,The limit。但他。哎,这个我们再这个还原回去,然后在这呢去begin,去这个create。Function。函数呢,名字已经起好了,那就是它CTRLC粘过来。嗯,好,然后这个呢,也是需要传入参数,传入的是dept下线ID,那显然呢,它是一个in的类型的啊,我们就这样写。啊,是一个int类型的啊,大家呢,如果需要多个参数呢,就在用逗号方式呢,去写多个就OK了。嗯,行,这样就行,然后呢,下边呢,叫returns,干什么事呢,查询这个部门的员工的人数,那显然呢,它是一个整形的对吧,那这样然后呢,我们下边呢,如果没有这些特征呢,你就不用写了,直接呢你就begin一下。
18:12
然后最后呢,End表示结束,然后在这里边呢,我们去写这个逻辑啊,Return什么呀,我们想查询的呢,是你这个部门的这个员工的人数好。Select,哎,我们就要count一个,不用count清了,诶from这个employees。然后where。这个department ID等于哎DEPID,哎,这样就可以了。从这个表里边查的对吧?行,那这样的话呢,我们就写完了啊,咱们选中呢,做一个执行。好没问题,然后下边呢,我们来看一下这个调用啊调用,那我这呢,用这个变量的方式吧,我们叫set一个,那我们叫dept。ID,那我这呢,比如说冒号等于负个值,比如说30号部门的,然后接下来我们通过select,哎,咱们具体的这个方式啊,CTRLC。
19:05
拿过来,哎,你把这个变量呢放进去。哎,这样,那这里呢,我们就相当于查询30号部门的这个员工的人数啊,有六个人啊,再换一个,比如说50号部门,哎,再选中的执行。哎,45人,哎,就是这样个意思。哎,就这个道理行,那这呢是咱们这个知识层面的一个讲解,我这儿呢,就用三道这个例题呢,给大家做一个说明,咱们课后呢,还有练习题,到时候呢,我们可以再做一些相关的一些题目啊,就这样啊好,那后边这块呢,我们对比一下这个存储函数和存储过程两个结构呢,咱们都讲完了,对吧,都讲完了。呃,那么开发当中我们到底会用哪一个呢?它们的区别是什么呀?来,我们简单的看一下这个表格,存储过程跟函数使用的关键字procedure跟function不一样,哎,这个调用呢叫call,这个呢调用呢叫做select啊。然后这个存储函数呢,我们是一定会有返回值的啊,我们都写了叫returns了啊,一定会有返回值的,对吧,在这里边儿呢,会有return呢,跟大家去搭配,而我们这个存储过程呢,大家可能会看到不同的地儿呢,这个信号不一样,有的时候呢,说哎,可以有零个或者多个返回值啊,那当然多个里边也包括一个了。
20:14
那有有同学就懵了,说哎,那这个存储过程不就也相当于是一种函数的一样吗?哎,其实这块呢,我们可以这样说啊,就是咱们理解为呢,有呃,这个零个或者多个这个返回值。这个所谓的返回值呢,其实就是我们通过上边那个参数是不是叫in out来表达的,对吧。你看啊,我们要是用的是in的话呢,表示的就是传进去,传进去的话呢,这个参数我们在里边呢,是要使用的,你比如说我们在这个位置呢,去使用了,而这个所谓的这个out呢,这是什么意思呢?其实这块也理解成是我们传入的一个参数啊,注意这也是咱们传入的一个参数,只不过呢,传入这个参数呢,有可能我们没有明确起它的这个值,然后在里边呢,它运行完以后呢,把这个值呢,写入到你这个变量里了,因为这个变量呢,你理解成是从外边传进来的,那你整个这个呃,存储过程执行完以后的话呢,那我们这个变量的值,这个变量呢,它的生命周期其实还在嘛,所以我这块呢,再去查的时候呢,自然而然这个值呢就有了。
21:09
你可以解成就是里边运行完以后呢,把这个数据写入到我们这个out这个参数里边了值啊我们查到了,所以呢,跟我们现在讲的这个函数,就是完全的说做一个return的这种方式呢,还是有区别的。啊,还是有区别的,这个大家呢,去感受一下这个OK。哎,像咱们这个大家呢,如果说学习过像Java语言的话呢,Java里边呢,我们那个呃方法,哎,说你有那个反回值类型那块啊,它其实对应的就相当于是我们这个函数。啊,这也是我们的函数啊。然后呢,应用场景诶这块呢,大家关注一下,对存储过程呢,大家会发现一般呢,咱们通常用于是叫更新的操作,而这个存储函数呢,通常是用于这种查询的操作啊,并以一个值的方式呢,给我们做的返回。哎,是这样的。啊,另外呢,这里边还有提到说存储函数呢,可以放在查询语句,可以放在查询语句中去使用存储过程不行,因为呢,我们这个,呃查询语句你像咱们前面呢,讲系统定义的,比如说你单行函数啊,还是多行函数啊,咱们是不是就在select中用过啊,就好比是咱们现在呢,讲我select这个位置,它不就是一个函数吗?或者咱们select round也好,窗nket也好,还有咱们讲的日期时间的啊,讲的这个字符串的这个数值类型的,呃,系统的相关的一些函数等等很多,因为呢,它相当于查完以后呢,就是一个结果,那我们就可以呢,是不是查询的时候呢,用这个结果呀。
22:28
对吧,那没问题,而我们这个存储过程呢。存储过程执行完以后呢,啥也没有。是吧,它没有这种所真正意义上所谓的这个返回值,说给你返回的东西了没有,所以说你就不能在这个产品局里边儿去使用啊,这是它的一个特别之处。啊,特别之处大家注意一下,那么反过来的话呢,我们说这个,呃,存储过程它这块呢,这个优点呢,就是它的功能呢,其实是更强大的啊,更强大的其实从这块儿也能感受得到。对吧,那其实你要是想记录多个这个值,你像我们这个只只能返回一个结果了啊,函数都是这样特征,那你要是有多个数据,就是相当于我们这个执行完一段逻辑之后呢,希望呢,比如返回好几个这个这个数据了,那这时候你可以用这个存储过程,然后呢,在我们这个参数里边是不是都标成这个out就行,然后把它传进去啊里边呢,一顿操作,把数据呢都写到这几个变量里边,那我们呢,运行完以后呢,是不是就拿到这几个值了呀,它就更灵活一些。
23:20
哎,注意它更灵活一些,所以功能呢会更强大。哎,这块大家也关注一下行,那么关于这个存储函数啊,咱们就,哎说到这儿。
我来说两句