• MySQL存储过程


    含义

    存储过程类似一个函数,数据库中也支持循环语句和判断语句。我们可以将所有的逻辑、判断和SQL语句全部写在数据库上面,然后取个名字,当程序来操作的时候,可以直接通过这个名字,就能执行对应的功能;不用传大量的SQL语句。

    存储过程

    一、创建存储过程

    关键字: procedure

    代码:

    create procedure proc_p1()

    说明:

    • create procedure:表示要创建存储。
    • proc_p1:是创建存储的名字。

    这样就创建了一个存储过程,名为proc_p1;但是此时里面并没内容。

    二、创建存储过程内容

    代码:

    create procedure proc_p1()
    begin
    内容放置位置
    end

    说明:
    要操作的内容必须放在,begin和end之间。

    案例:

    数据库内容:

    1481363283163

    操作代码:

    create procedure proc_p1()
    BEGIN
    select * from part;
    END

    结果;生成的对象会存储在函数中;

    1481363470713

    三、调用存储过程

    关键字:CALL

    代码:

    CALL proc_p1();

    四、删除存储过程

    代码:

    drop procedure proc_p1;

    问题:能否修改存储过程那?

    答案是肯定的,但是却很繁琐,因此我们一般修改的时候,都是重写存储过程。

    因此,针对修改我们的操作(也是重写):

    delimiter $$drop procedure proc_p1 $$
    create procedure proc_p1()
    BEGIN
      select * from part;
    END $$delimiter ;
    代码

    分析:
    即先删除,后写入。

    问题:如果删除的时候,没有对应的存储过程那?

    答案:会报错!
    因此我们要避险这种情况出现。

    delimiter $$drop procedure if EXISTS proc_p1 $$
    create procedure proc_p1()
    BEGIN
      select * from part;
    END $$delimiter ;
    代码

    分析:
    增加了if EXISTS判断;它表示,如果后面的这个存储过程有则删除,反之不操作;这样避免报错,导致问题。

    上面的代码都是简单的操作,再看下面的代码:

    有参数的存储过程

    一、参数 in

    delimiter $$drop procedure if EXISTS proc_p1 $$
    create procedure proc_p1(
      in i1 int
    )
    BEGIN
    declare d1 int;
    declare d2 int default 2;
    set d1 = i1 + d2;
    END $$delimiter ;
    in

    分析:
    in:表示进的,接收参数
    declare:表示声变量。
    int:表示变量类型
    default:表示设置变量的初始值。
    set:表示赋值操作,也可以理解为设置值。

    自定义代码的结束符号

    delimiter

    drop procedure if EXISTS proc_p1;
    create procedure proc_p1()
    BEGIN
    select * from part;
    END

    上面代码在Navicat下是能执行的,但是在终端上是要出问题的。
    原因就是这个分号;上面的代码begin和end间代码,表示一个功能,都是整体传进去的,但是,代码在执行的时候,遇到分号;则表示此功能的代码执行完毕。所以导致后面的代码不执行,在终端的运行,因为分号的原因,会导致运行的时候出问题,所以,分号要是用在不对的位置,会造成很大的麻烦。

    说明:
    这个的意思就表示,以后的mysql语句都是以 $$为结束。

    注意:

    自定义的时候不能将 \ 设置用来结束;\ 在终端会报错!可能是转义符的原因吧。

    验证上面的说明:

    在终端进入mysql客户端,当我们输入的代码不带分号的时候,结果,会一直处于等待命令的状态:

    1481380025299

    加上分号:出结果

    1481380109694

    问题:如果我们这样改动的话,获导致全局都受影响,因此我们可以让这种效果,只在指定范围有效,离开这个范围,有还原会之前?

    所以,完整的代码:

    delimiter $$
    drop procedure if EXISTS proc_p1 $$
    create procedure proc_p1(
    in i1 int
    )
    BEGIN
    declare d1 int;
    declare d1 int;
    set d1 = i1 + d2;
    END $$
    delimiter ;
    完整代码

    说明:

    我们在end后加上 $$ 表示一个功能的代码结束,并在最后,又将设置还原会去。还是以分号结尾,这样其他代码不受影响

    下面接着存储参数in分析

    二、参数 out

    代码:

    delimiter $$
    drop procedure if EXISTS proc_p1 $$
    create procedure proc_p1(
    in i1 int,
    out i2 int
    )
    BEGIN
    declare d2 int default 3;
    if i1 = 1 then
    set i2 = 100 + d2;
    elseif i1 = 2 THEN
    set i2 = 200 + d2;
    else
    set i2 = 1000 + d2;
    end if;
    END $$
    delimiter ;
    
    -- 加入回话变量 @u;
    call proc_p1(1, @u);
    
    select @u;
    out

    结果:

    1481382276828

      • 说明:
        @u:默认其值为 none;回话变量,相当于我们在外面创建了一个变量,并将引用传入 proc_p1函数,这个传入的引用会被 i2 接收,所以,间接的也相当于在给这个 @u 赋值。
    • out:字面意思理解,出;有返回的意思。

    三、参数 inout

    delimiter $$
    drop procedure if EXISTS proc_p1 $$
    create procedure proc_p1(
    in i1 int,
    inout ii int,
    out i2 int
    )
    BEGIN
    declare d2 int default 3;
    if i1 = 1 then
    set i2 = 100 + d2;
    set ii = ii + 1;
    elseif i1 = 2 THEN
    set i2 = 200 + d2;
    else
    set i2 = 1000 + d2;
    end if;
    END $$
    delimiter ;
    
    -- 加入回话变量 @u;
    
    set @o = 5;
    call proc_p1(1, @o, @u);
    
    select @o,@u;
    inout

    结果:

    1481382917130

    分析:
    inout:从字面意思理解”进、出”,表示要接收一个带值的变量,同时函数执行完后,也会将对应的变量返回。

    扩展:sql中@变量

    带上一个@叫用户变量:只要用户还登录着,这个变量就有效;不管在那个代码块中都有效;除非用户被关闭。

    带上2个@叫全局变量。

    注意:用户变量和函数的局部变量的区别

    • 用户变量:只要用户还登录着,这个变量就有效;不管在那个代码块中都有效;除非用户被关闭。
    • 局部变量:离开函数就没用了。

    python操作数据库存储过程

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import pymysql
    
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 执行存储过程
    cursor.callproc('proc_p1', (1,2,3))
    # 获取执行完存储的参数
    cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
    result = cursor.fetchall()
    
    conn.commit()
    cursor.close()
    conn.close()
    
    print(result)
    代码

    说明:
    cursor.callproc(‘proc_p1’, (1,2,3)):只能给数据库中的proc_p1存储方法;根据前面的我们知道数据库中的proc_p1;只能接收2个参数,所以,即使你传入了3个也只有2个能用。后面的会自动忽略。

    上面的数据库中的存储过程,没有SQL语句,只是简单的,变量操作,但是,如果我们加入SQL操作,那我们在python中怎样获取这个SQL语句操作的结果那?

    获取存储过程的查询结果:

    cursor.fetchall()

     问题:怎样获取变量的返回值那?

    cursor.execute("select @_p1_0”)

    分析:
    1、首先要用select
    2、一个@_
    3、后面在接存储过程的名字。
    4、接 _0:表示索引。表示获取返回第一个值,要想获取后面的,则依次往后指定,用逗号隔开便可。

    cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")

    这个获取获的值,存放在游标里面的,所以,要获取具体的值,可以通过游标结合fetchone获取:

    result = cursor.fetchone()

    特殊:
    虽然存储过程中,in接收参数,但是在python中获取存储过程数据的时候,in接收传入的值,会被返回,所以,获取的第一个值,便是,callproc执行的时候,传入的第一个参数.

    python获取存储过程分两步:

    • 获取SQL语句执行的返回值
    • 获取存储函数的变量返回值

     1481385274669

  • 相关阅读:
    模拟测试69
    模拟测试68
    模拟测试66
    NOIP模拟测试15
    NOIP模拟测试14
    Gekoo's checker
    NOIP模拟测试13
    替罪羊树模板
    KDTree笔记
    NOIP模拟测试12
  • 原文地址:https://www.cnblogs.com/jayafs/p/6175770.html
Copyright © 2020-2023  润新知