MySQL存储过程

Posted 手里有糖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于MySQL存储过程的主要内容,如果未能解决你的问题,请参考以下文章

如何从 PHP 代码中调用 MySQL 存储过程?

如何从 PHP 代码中调用 MySQL 存储过程?

如何从 PHP 代码中调用 MySQL 存储过程?

java 登录过程 - android片段,异步任务登录,Asp.net控制器,存储库

[转]MYSQL 创建存储过程

怎么在mysql中查询已建立的存储过程