【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容)

【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容)

存储过程:一组预编译的SQL语句和流程控制语句,被命名并存储在数据库中。存储过程可以用来封装复杂的数据库操作逻辑,并在需要时进行调用。

类似的操作还有:自定义函数、.sql文件导入。

我们先从熟悉的函数开始说起:

自定义函数

User- (UDF)允许创建 可以在SQL查询中调用的函数,以便在执行特定操作或逻辑。

创建函数:

create function 函数名(参数名 数据类型,...) -- 参数列表
returns 返回值类型
[deterministic]
begin
    -- 函数体
    return 返回值;
end;

关键字: 汉译为 ‘确定的’ 。在.0版本以上,创建函数必须在该位置添加关键字,否则会报错:

如果加上关键字的话:

另外需要注意的是:在指明函数返回值类型时,使用的关键字是 ,在函数体内部返回值时使用的是  。注意区别,不要写错。

删除函数:

将自定义函数删除,语法:

drop function [if exists] myfuc;

调用函数:

使用自定义函数的方法与使用内置函数的方式一样,执行语句:

select myfuc();

变量

变量的声明:关键字

declare variable datatype [default val];
-- eg.
declare age int default 18;

变量的赋值:关键字set

set variable = val;
-- eg.
set age = age + 10;

注意事项:

第一、函数的参数是已经声明好的变量,无需再次声明,可以直接使用

第二、声明变量的语句必须在函数体的最上方,其次才可以是其它语句

第三、函数体外的SQL语句也可以设置变量,语法为:【set @ = val】

在函数体内执行sql语句为变量赋值:

-- function_head
begin
    declare val int default 0;
    select count(*) into val from emp;
    return val;
end;

在该示例中,就将查询的结果直接赋给变量val。

结构语句分支结构

SQL语句中一共有两种分支结构【if/case】,但这两种分支结构的语法用法却与我们熟知的语言的写法不同,但很好理解。下面我们就具体看一下:

第一种分支语句:if then…else if then…else…end if;

if condition1 then
    -- coding1
else if condition2 then
    -- coding2
else if condition3 then
    -- coding3
else
    --codingn
end if;

与我们常见的C/C++的代码作用域以花括号作为界符不同,SQL语言使用 end显式指定该作用域结束。上面定义函数时begin……end;就已经体现了。在if里面作为begin的等价关键字为:then。编译器一旦识别then就知道进入if的内部作用域了。再次识别到其它的else if或者end ifmysql复杂存储过程,就会跳出本作用域进入下一个作用域。

第二种分支语句:case   when then…when then… else… end case;

case
    when condition1 then
        -- exp1...;
    when condition2 then
        -- exp2...;
    else
        -- expn...;
end case;

case语句与我们熟悉的语法也不一样mysql复杂存储过程,不过也很好理解:遇到case直接进入分支,然后判断条件,满足即then执行作用域内的逻辑代码或表达式。最后有一个else相当于C/C++中的,都不满足就给个默认入口。最后以end case结束分支作用域。

循环结构

同样的,循环结构也有两种语法:【while/】。

第一种循环语句:while (bool) do … end while;

while _condition_ 
do
    --
    -- coding    
    --
end while;

当条件满足时 do执行循环体,直到条件不满足【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容),end while结束循环。

第二种循环语句: … until (bool) end ;

repeat
    --
    -- coding
    --
until _condition_ 
end repeat;

与while循环不同,while循环时满足条件才执行。这种循环语句是,当满足了条件时,会结束这个循环。

存储过程

存储过程类似于自定义函数的语法,但是有区别的。例如:无返回值、传入的参数方式不同、可以使用游标等。

基础语法

无参语法:

-- 创建存储过程
create procedure 存储过程名()
begin
   -- 存储过程的逻辑代码
   -- 可以包含SQL语句、控制结构和变量操作
end;

调用存储过程:

-- 执行存储过程
call procedure 存储过程名();

删除存储过程:

-- 删除存储过程
drop procedure [if exists] 存储过程名;

参数详解

create procedure 存储过程名(
    [in|out|inout] 参数名 参数的数据类型,
    [in|out|inout] 参数名 参数的数据类型,
    ......
)
begin
    -- 存储过程的逻辑代码
    -- sql语句、结构语句、变量操作等
end;

类型修饰符

存储过程的每个参数都有输入输出修饰【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容),默认为:in输入参数

in(默认):输入参数,存储过程的输入值,从外部传递给存储过程,存储过程内部是只读的,不能修改它的值。【】

out:输出参数,存储过程的返回值,存储过程可以修改它的值并将其返回

inout:输入和输出参数,既可以作为输入值传递给存储过程,也可以由存储过程修改并返回。

进阶语法

我们现在有一个需求,需要查询emp表,为每个员工加100元薪资。

现在遇到的难点是:emp表查询到的结果不是单一结果,只知道sal的字段类型为int,那么如何将结果集的每一条记录依次取出来呢?

我们需要学习一个新的知识:游标-

!!!注意!!!

在MySQL中,存储过程允许使用游标来处理结果集,但函数里不行。可能是因为函数的设计用途不同。函数通常被要求是确定性的,或者至少在某些上下文中不允许有副作用,而游标可能涉及到对结果集的操作,可能引起非确定性的结果或者副作用。或者,函数的执行环境限制了一些操作,比如不允许修改数据库状态,而游标可能用于逐行处理,但函数需要返回单个值,这样的结构不支持

游标

在MySQL中,游标是一种数据库对象,它能够让你对结果集逐行进行处理。在操作数据库时,普通的SQL语句通常会对整个及进行操作,但在我们上述的场景下,就需要逐行的处理数据,这时有标记就能发挥作用了。

游标的使用步骤:声明=》打开=》读取=》关闭=》释放

-- 声明游标
-- 定义游标的名称 并绑定查询语句
declare cs cursor 
for
select empno from emp;

游标就类似于C++实例化出来的对象:cs为对象名mysql复杂存储过程,对象类型为-游标,绑定查询语句就是传入构造参数初始化游标的。

-- 打开游标
-- 执行定义好的查询语句 把结果集存在游标中
open cs;

联系熟悉的C++帮助理解:open 就是对象的一个成员函数,作用是执行绑定的sql语句获取结果集的。

-- 读取数据
-- 借助fetch语句从游标逐行获取数据
fetch cs into val;

fetch 就是游标的另一个成员函数:换个名字理解:-获取下一条数据,内部有一个偏移量,再次执行时,就是取结果集的下一个了。跟文件操作的偏移量联系一下也不难理解。

-- 关闭游标
-- 结束对结果集的操作后,关闭游标以释放资源
close cs;

调用内部成员函数close,相当于调用clear函数

最后还有一个释放游标,也就是从内存中移除游标的阶段。

注意事项:

异常处理:错误处理-句柄

上面我们也说了,游标在使用时可能会出现异常情况。例如:循环次数过多,但数据集项数少于循环次数,那么会产生异常情况。下面给出一段代码:

create procedure mypro() 
begin 
    declare i int default 0;
    declare eid int;
    declare cs cursor
    for
    select empno from emp;
    open cs;
    while i<20 do
        fetch cs into eid;
        select sal from emp where empno=eid;
        set i = i+1;
    end while;
    close cs;
end;

已知,我们的emp表一共只有14条记录,那怎么从cs中取二十次数据呢?肯定会出错的,这个异常一旦出现,我们如何处理呢?SQL就提供了一种异常处理机制:句柄

句柄-处理类型:

– 继续执行后续代码 – 用于可恢复的错误(数据遍历结束)

exit – 退出当前代码块 – 用于不可恢复的错误(如事务冲突)

错误-条件类型:

not found – 未找到

– sql异常

– sql警报

特定错误码 -如1062主键冲突

根据笛卡尔积的形式,从两个类型集合中任取一个都可以组成一个异常处理类型。

    -- 声明处理句柄
    declare continue handler for not found 
        set done=1;
    declare exit handler for sqlexception
        begin
            rollback; -- 回滚事务
            set errmsg="错误信息";
        end;
    declare continue handler for sqlwarning 
        set done=2;

感谢大家!

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » 【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容)

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们