17 存储过程

过程:

封装了若干条语句.调用时,这些封装体执行.

函数:

是一个有返回值的过程.

过程是没有返回值的函数

存储过程:

把此过程存储在数据库中,因此称为存储过程

存储过程语法

# 创建语法:
    create procedure procedureName()
    begin
        -- sql语句
    end$

# 删除存储过程
    drop procedure procedureName;

# 查看已有的procedure
    show procedure status;

# 调用存储过程:
    call procedureName();

存储过程1--创建简单的存储过程

# eg:
    create procedure p1()
    begin
        select * from tableName;
    end$

存储过程2--引入变量

# 存储过称是可以编程的,意味着可以使用变量,表达式,控制结构    
# eg:
    create procedure p2()
    begin
        declare age int default 18;
        declare height int default 180;
        select concat('年龄是',age,'身高是',height);
    end$

存储过程3--变量运算

# 存储过称中,变量可以在sql语句中合法的运算,如+-*/,注意运算的结果是如何赋值给变量
# 语法--set 变量名 := expression
# eg:
    create procedure p3()
    begin
        declare age int default 18;
        declare height int default 180;
        set age := age + 20;
        select concat('20年后年龄是',age,'身高是',height);
    end$

存储过称4--控制结构(if/else)

# 语法:
    if 
        conditon 
    then
        statement
    else
        statement
    end;

# eg:
    create procedure p4()
    begin
        declare age int default 18;
        if age >= 18 then
            select '已成年';
        else
            select '未成年';
        end if;
    end$

存储过称5--控制结构2(while)

# 三种控制结构:  
    顺序,选择,循环

# eg: 求1-100的和
    create procedure p5()
    begin
        declare total int default 0;
        declare num int default 0;

        while num <= 100 do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$ 

存储过称6--控制结构3(case)

# 用if/else也能实现同样的效果
# eg: 
    create procedure p6()
    begin
        declare pos int default 0;
        set pos := floor(5*rand());

        case pos
            when 1 then select 'fly';
            when 2 then select 'sea';
            else select 'run';
        end case;
    end$  

存储过称7--控制结构4(repeat)

# 用while也能实现同样的效果
# eg: 
    create procedure p7()
    begin
        declare total int default 0;
        declare i int default 0;

        repeat
            set i := i+1;
            set total := total + i;
            
        until i>=100
        end repeat;
        
        select total;
    end$ 

存储过称8--传参

# 存储过程的括号里,可以声明参数,
# 语法:  
    [in/out/inout] 参数名 参数类型,不写时,默认为in

# 调用: 
    call p8(3,4)

# eg:
    create procedure p8(width int , height int)
    begin
        select concat('你的面积是',width * height) as area;

        if width > height then
            select '宽大于高';
        elseif width < height then
            select '宽小于高';
        else
            select '宽等于高';
        end if;
    end$

存储过称9--in型参数

# 存储过程中可以接收到这个参数
# eg: 求1-n的和
    create procedure p9(in n int)
    begin
        declare total int default 0;
        declare num int default 0;

        while num <= n do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$

存储过称10--out型参数

# 将存储过程中值输出
# 调用: 
    call p10(100,@argsName)

# eg: 求1-n的和
    create procedure p10(in n int,out total int)
    begin
        declare num int default 0;
        set total := 0;

        while num <= n do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$
# 此处执行完成后,输入select @argsName即可得到对应的结果

存储过称11--inout型参数

# 调用: 
    set @age = 18
    call p11(@age)

# eg:   
    create procedure p11(inout age int)
    begin
        set age := 1;
        set age := age + 20;
    end$

存储过称12--cursor 游标

# 一条sql,对应N条资源,取出资源的接口/句柄,就说游标
# 沿着游标,可以一次取出一行

# eg: 
    create procedure p12()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        -- 这种方法不推荐使用
        -- 定义一个游标
        declare cursorName cursor for select gid,num,name from goods;

        open cursorName;
            -- 将显示的第一行值赋予对应的变量
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

            -- 将显示的第二行值赋予对应的变量
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

            -- 将显示的第三行值赋予对应的变量(如果只有两条数据,赋值三次会报错)
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

        close cursorName;
    end$

存储过称13--cursor 游标(推荐使用)

# eg:
    create procedure p13()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare i int default 0;
        -- 定义一个变量,用来计算显示了几条数据
        declare cnt int default 0;

        -- 定义一个游标
        declare cursorName cursor for select gid,num,name from goods;

        select count(*) into cnt from goods;

        open cursorName;

            repeat
                set i := i +1;
                fetch cursorName into row_gid,row_num,row_name;
                select row_gid,row_num,row_name;
            until i >= cnt
            end repeat;
        
        close cursorName;
    end$

存储过称14--越界标志(continue handler for not found)

# 在MySQL cursor中,可以declare continue handler来操作一个越界标志
# 语法: declare continue handler for not  found 语句;
# 表中只有三条数据,但是下面的代码执行后 ,会取出四行,最后一行显示两次
# 代码中有逻辑错误,分析:
    当第四次执行 repeat 时,fetch-->没有数据,触发越界标志中的not  found-->set you := 0-->continue-->执行fetch后面的sql语句(select row_gid,row_num,row_name;)-->所以,最后一行被取出两次

# eg:
    create procedure p14()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定义一个游标
        declare cursorName cursor for select gid,num,name from goods;
        declare continue handler for not found set you := 0;

        open cursorName;

        repeat
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;
        until you = 0
        end repeat;
        
        close cursorName;
    end$

存储过称15--越界标志(exit handler for not found)

# 越界标志解决逻辑错误(不完善,没考虑到表为空的情况)
# 引入另一种越界标志:declare exit handler for not found 语句;

# eg:
    create procedure p15()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定义一个游标
        declare cursorName cursor for select gid,num,name from goods;
        declare exit handler for not found set you := 0;

        open cursorName;

        repeat
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;
        until you = 0
        end repeat;
        
        close cursorName;
    end$

存储过称16--越界标志(undo handler)

# 除以上两种越界标志(continue,exit)外,还有undo handler
# continue是触发后,后面的语句继续执行
# exit是触发后,后面的语句不再执行
# undo是触发后,前面的语句撤销(MySQL暂不支持)


# 不改变越界标志,解决逻辑错误(完善)
# eg: 
    create procedure p16()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定义一个游标
        declare cursorName cursor for select gid,num,name from goods;
        declare exit handler for not found set you := 0;

        open cursorName;
            -- 1: 先取出一行数据,如果取出,则 not found未触发,
            fetch cursorName into row_gid,row_num,row_name;

            repeat
                -- 2: 执行显示语句
                select row_gid,row_num,row_name;
                -- 3: 在进行fetch如果取不到,触发continue越界标志,继续向下执行,
                -- 下面没有sql语句,所以不会再显示
                fetch cursorName into row_gid,row_num,row_name;
            until you = 0
            end repeat;
        
        close cursorName;
    end$
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • oracle存储过程常用技巧 我们在进行pl/sql编程时打交道最多的就是存储过程了。存储过程的结构是非常的简单的...
    dertch阅读 3,493评论 1 12
  • 我们在进行pl/sql编程时打交道最多的就是存储过程了。存储过程的结构是非常的简单的,我们在这里除了学习存储过程的...
    AlbenXie阅读 2,968评论 1 3
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,625评论 18 399
  • 1.1 基本结构 PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分。 1.2 命名规则 1.3 记...
    慢清尘阅读 3,850评论 3 14
  • 往往看别人的代码会有这样的感慨:看不懂理还乱是离愁别是一番滋味在心头 为什么要使用存储过程? 在mysql开发中使...
    老马的春天阅读 2,105评论 0 9