MySql存储过程

2023-11-12

一、Mysql存储过程概述

存储过程是数据库的一个重要对象(对象还包括,索引,触发器,视图等),可以封装sql语句集,用来完成比较复杂的业务逻辑,并且还可以入参,出参。

存储过程创建时会进行预编译进行保存,当下次调用时不需要再进行编译。

优点:

    在生产环境下,可以通过直接修改存储过程的方式修改业务逻辑(或bug),而不用重启服务器。
    执行速度快,存储过程经过编译之后会比单独一条一条执行要快。
    减少网络传输流量。
    方便优化。
缺点:
    过程化编程,复杂业务处理的维护成本高。
    调试不便
    不同数据库之间可移植性差。-- 不同数据库语法不一致!

二、语法结构 

一、delimiter

声明结束符;

delimiter //

//:代表的是结束标志,这么做的目的主要是使结束标志与进行分开,原因是存储过程中可能会有其他的一些操作语句需要用到,但是存储过程又还没有执行完,所以就需要特别定义一个结束标志。否则存储过程在执行过程中就会认为;是结束标志,然后结束存储过程,可能会导致出错或后面操作无法执行完。

二、 语法体结构

create procedure 名称([proc_parameter[....,.....,.....]])

        [characteristic ...] routine_body

end (delimiter 声明的结束标识符)

-- proc_parameter参数部分,可以如下书写:
 [ IN | OUT | INOUT ] param_name type
 -- type类型可以是MySQL支持的所有类型
 
-- routine_body(程序体)部分,可以书写合法的SQL语句 BEGIN ... END

 栗子:

-- 声明结束符。因为MySQL默认使用‘;’作为结束符,而在存储过程中,会使用‘;’作为一段语句的结束,导致‘;’使用冲突

delimiter $$
create procedure select_demo()
begin
    select 'hello';
end $$


-- 调用存储过程 单独调用使用;,如果是接着上面的话,就用$$
call select_demo();

一、变量以及赋值

一、局部变量:用户自定义,在begin/end中有效

声明变量语法:declare var_name type [default var_value];

栗子:declare name varchar(32);

1.使用set进行赋值

delimiter $$

create procedure demo()

begin

declare name varchar(32) default 'tom';

set name = 'bob';

select name;

end $$

 2.使用into赋值

delimiter $$

create procedure demo()

begin

declare tp_name varchar(32) default 'tom';

declare tp_age int default 12;

select e.age,e.name into tp_age,tp_name from emp e where e.no = 9527;

select tp_name,tp_age;

end $$

二、用户变量

用户自定义变量,当前会话【连接】有效。

栗子:

delimiter $$

create procedure demo()

begin

declare name varchar(32) default 'tom';

set @name = 'bob';// 直接使用就行

select name;

end $$

 三、入参、出参

语法:in | out | inout param_name type

栗子:

-- in 栗子

delimiter $$

create procedure demo(in name varchar(32))

begin 

set @name = name;

end $$

 -- out栗子

delimiter $$

create procedure demo(in name varchar(32),out age int(11))

begin

select d.age into age from dept d where d.name = name;

// 注意此处,要么表起别名,要么就是入参和字段名不能一致

end $$

--测试

set @dept_no = 100;
call sp_param01('DALLAS',@dept_no);
select @dept_no;

-- INOUT类型

delimiter $$

create procedure demo(inout name varchar(32))

begin

set name = concat('hello',name);

end $$

--测试

set @name = 'world';

call demo(@name);

select @name;

二、流程控制

1、if

语法:

IF search_condition THEN statement_list
    [ELSEIF search_condition THEN statement_list] ...
    [ELSE statement_list]
END IF

栗子:

-- 需求:入职年限<=3是新手 >3并且<=6老员工 >6元老
-- timestampdiff函数:timestampdiff(unit,exp1,exp2) 取差值exp2-exp1差值,单位是unit

delimiter $$
create procedure demo()
begin
declare result varchar(32);
declare years int;
select timestampdiff(year,e.datetime,now()) into years from emp e where e.no = 9527;

if years >6 then set result = '元老'
else if 
years >3 and years <= 3 then set result ='老员工'
else
set result ='新员工'
end if;

select result;  // 查询一下结果
end $$

2、case

此语法是不仅可以用在存储过程,查询语句也可以用!

-- 语法一(类比java的switch):
CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE
-- 语法二:
CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

栗子:

-- 需求:入职年限<=3是新手 >3并且<=6老员工 >6元老
-- timestampdiff函数:timestampdiff(unit,exp1,exp2) 取差值exp2-exp1差值,单位是unit

delimiter $$
create procedure demo()
begin
declare result varchar(32);
declare years int;

select timestampdiff(year,e.datetime,now()) into years from emp e where e.no = 9527;

case 
when years >6 then set result = '元老'
when  years >3 and years <= 3 then set result ='老员工'
else
set result ='新员工'
end case;

select result;  // 查询一下结果
end $$

3、循环控制

loop:

-- LOOP语法
[begin_label:] LOOP
    statement_list
END LOOP [end_label]

栗子:

需要说明,loop是死循环,需要手动退出循环,我们可以使用leave来退出。

可以把leave看成我们java中的break;与之对应的,就有iterate(继续循环)——类比java的continue

-- 需求:循环打印1到10

--leave控制循环退出
delimiter $$
create procedure sp_flow_loop()
begin
 declare c_index int default 1;
 declare result_str  varchar(256) default '1';
 cnt:loop
 
  if c_index >= 10
  then leave cnt;
  end if;

  set c_index = c_index + 1;
  set result_str = concat(result_str,',',c_index);
  
 end loop cnt;
 
 select result_str;
end$$

--leave + iterate控制循环退出
delimiter $$
create procedure demo()
begin
declare index int(11) default 1;
declare result varchar(32) default '1';

nums:loop
    set index = index + 1;
    set result = concat(result,',',index);
    
    if index < 10
        then
     iterate nums;
    end if;
     leave nums;
 end loop nums;
select result;
end $$
 

repeat :类似于do------while();

语法结构:

[begin_label:] REPEAT
    statement_list
UNTIL search_condition -- 直到…为止,才退出循环
END REPEAT [end_label]

栗子:

delimiter $$
create procedure demo()
begin 
    declare index int(11) default 1;
    declare result varchar(32) default '1';

nums repeat:
    index = index + 1;
    result = concat(result,',',index);
    until index > 10;
end repeat nums;
select result;
end $$

while:相当于java的while(){}语句

[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

 栗子:

delimiter $$
create procedure demo()
begin 
    declare index int(11) default 1;
    declare result varchar default '1';

while index <10 do
    set index = index + 1;
    set result = concat(result,',',index);
end while;
select result;
end $$ 

三、游标

用游标的到一个结果集,然后进行逐行处理

-- 声明语法
DECLARE cursor_name CURSOR FOR select_statement
-- 打开语法
OPEN cursor_name
-- 取值语法
FETCH cursor_name INTO var_name [, var_name] ...
-- 关闭语法
CLOSE cursor_name

栗子:

delimiter $$ 
create procedure demo(in dept_name vachar(32))
begin
    declare e_no int;
    declare e_name varchar(32);
    declare e_sal decimal(7,2);
    
    declare flag boolean default true;

-- 声明游标
    declare emp_curesor cursor for   
    select e.empno,e.ename,e.sal
    from emp e,dept d
    where e.deptno = d.deptno and d.dname = dept_name;  

--声明句柄,主要是用于进行数据逐行遍历的时候,遍历到最后,没有数据的时候返回报错的一个判断
--这里使用continue(表示:如果数据遍历完了,就退出循环,执行循环外的代码),如果使用exits(则不会执行循环外的代码),
    declare continue handler for NOT FOUND set flae = false;
    
-- 打开语法
    open  emp_curesor;
-- 取值
    emp_loop:loop
    if flag then 
        select e.empno,e.ename,e.sal
    else
        leave emp_loop;
    end if;
        end loop emp_loop;
-- 设置标志,看是否执行到这里
    set @end_flag = 'end_flag';
end $$    


call demo('RESEARCH');
     

 特别注意:

在语法中,变量声明、游标声明、handler声明是必须按照先后顺序书写的,否则创建存储过程出错。

 四、handler句柄

语法:

DECLARE handler_action HANDLER
    FOR condition_value [, condition_value] ...
    statement

handler_action: {
    CONTINUE
  | EXIT
  | UNDO
}

condition_value: {
    mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
}

mysql数据库报错信息:
CONTINUE: Execution of the current program continues.
EXIT: Execution terminates for the BEGIN ... END compound statement in which the handler is declared. This is true even if the condition occurs in an inner block.


SQLWARNING: Shorthand for the class of SQLSTATE values that begin with '01'.
NOT FOUND: Shorthand for the class of SQLSTATE values that begin with '02'.
SQLEXCEPTION: Shorthand for the class of SQLSTATE values that do not begin with '00', '01', or '02'.

 -- 各种写法:
 DECLARE exit HANDLER FOR SQLSTATE '42S01' set @res_table = 'EXISTS';
 DECLARE continue HANDLER FOR 1050 set @res_table = 'EXISTS';
 DECLARE continue HANDLER FOR not found set @res_table = 'EXISTS';

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySql存储过程 的相关文章

随机推荐

  • 返回json带转义符时的处理方法Content-Type: text/plain;

    当从json文件中读取json数据返回前端时 Content Type不同会导致返回给前端的数据结构也不同 Content Type text plain charset UTF 8 text plain的意思是将文件设置为纯文本的形式 浏
  • SQL删除重复数据只保留一条

    用SQL语句 删除掉重复项只保留一条 在几千条记录里 存在着些相同的记录 如何能用SQL语句 删除掉重复的呢1 查找表中多余的重复记录 重复记录是根据单个字段 peopleId 来判断 select from people where pe
  • vue 孙组件给父组件传值

    1 在孙组件里定义事件 通过 emit把值传出去 孙组件 planPop vue
  • unity键盘按键版垃圾分类

    有个键盘控制版的垃圾分类 打开程序后按任意键进行游戏 共分为可回收垃圾 厨余垃圾 有害垃圾 其他垃圾 游戏时间一共60s 按1 2 3 4分别会使垃圾到对应的垃圾桶 放对垃圾就会打开垃圾桶 放错垃圾桶会有放错提示 60s后会计算成绩 按任意
  • JS逆向新技术--JSRPC

    声明 本文章中所有内容仅供学习交流 不可用于任何商业用途和非法用途 否则后果自负 如有侵权 请联系作者立即删除 由于本人水平有限 如有理解或者描述不准确的地方 还望各位大佬指教 介绍 JSRPC意思就是远程调用js代码 全称 Remote
  • java树形数据结构递归求上级,附答案

    Part 1微服务架构设计概述 1 1 传统应用架构的问题 1 2 微服务架构是什么 1 3 微服务架构有哪些特点和挑战 1 4 如何搭建微服务架构 Part 2微服务开发框架 2 1 Spring Boot 是什么 2 2 如何使用Spr
  • sql注入利用union来绕过括号过滤

    union盲注 当我们在括号被过滤的时候 就不能使用substr mid 等多种函数 于是想到union 要想知道uinon的怎么进行盲注 就要了解union 这里给大家看几个mysql的查询语句 通过这三条语句我们可以看到 我们我利用un
  • STM32自定义printf功能方法

    最近在朋友那学到了如何重定义STM32的printf类似函数 在这做下记录 调用C语言库函数文件具体是哪一个我忘记了 都加上吧 include
  • ps制作鲨鱼在橙子“海洋”里游泳的创意画面

    预览效果 1 新建画布725X450 打开素材 把橘子放进去 并且把中间部分用钢笔工具抠出来 操作 1 使用钢笔工具在 橘子果肉的边缘点击 形成闭合路径 2 按ctrl 回车键 将其变成选区 蚂蚁线 3 将选区 存储起来 2 将水面素材拖入
  • 学习大数据必须掌握的核心技术概念

    随着数字化时代的到来 大数据成为了各行各业的关键资源 学习大数据的核心技术概念是成为一名优秀数据专家的关键 本文将介绍几个大数据的核心技术概念 并提供相应的源代码示例 帮助读者更好地理解和应用这些概念 分布式存储和处理 在大数据领域 数据量
  • CentOS7 安装 NVIDIA Container Toolkit

    安装containerd io sudo yum install y https download docker com linux centos 7 x86 64 stable Packages containerd io 1 4 3 3
  • vue遍历Map,Map在vue中的使用方法

    Map在vue中的使用方法 html 遍历的时候要遍历两遍
  • 《数据结构》--内部排序算法比较

    题目 各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶 或大概执行时间 试通过随机的数据比较各算法的关键字比较次数和关键字移动次数 以取得直观感受 基本要求 1 从以下常用的内部排序算法至少选取5种进行比较 直接插入排序 折半折
  • C# 位操作

    位操作符是对数据按二进制位进行运算的操作符 位操作是其他很多语言都支持的操作 如C C 和Java等 C 也不例外支持位操作 注意位操作支持的数据类型是基本数据类型 如byte short char int long等 C 支持的位操作有如
  • 逐行读取csv文件的某一列以及写入数据

    1 在Python中 你可以使用内置的csv模块来读取CSV文件 并逐行读取指定的某一列 下面是一个示例代码 展示如何逐行读取CSV文件的某一列 import csv 打开CSV文件 with open your file csv r as
  • webpack4之代码分割splitChunks和压缩优化

    我们打包出来的js文件 只要修改或增加了内容 就会导致入口js文件的hash变化 从而重新打包 为了提高打包速度 每次变化仅仅是重新打包自定义代码部分 webpack4提供了optimization splitChunks 回顾一下 web
  • 【Linux之shell脚本实战】批量上传docker镜像到华为云容器镜像仓库

    Linux之shell脚本实战 批量上传docker镜像到华为云容器镜像仓库 一 脚本要求 二 检查本地环境 1 检查系统版本 2 检查系统内核 三 检查本地容器镜像 四 shell注释模板配置 1 配置 vimrc 2 查看注释模板效果
  • MediaCodec问题汇总

    参考 http blog csdn net mincheat article details 51385144 MediaCodec的基本用法 网上一大把 这里就不写了 1 获取支持分辨率问题 Camera Parameters param
  • 设计模式-责任链模式(Java)

    设计模式 责任链模式 在极客学院的视频中学习了一种设计模式的方式 责任链模式 在博客园中发现了这篇文章 讲的很详细 就把它的一些内容转载过来了 本文中 我们将介绍设计模式中的行为型模式职责链模式 职责链模式的结果看上去很简单 但是也很复杂
  • MySql存储过程

    一 Mysql存储过程概述 存储过程是数据库的一个重要对象 对象还包括 索引 触发器 视图等 可以封装sql语句集 用来完成比较复杂的业务逻辑 并且还可以入参 出参 存储过程创建时会进行预编译进行保存 当下次调用时不需要再进行编译 优点 在