最全总结 | 聊聊 Python 数据处理全家桶(存储过程篇)

2021-08-06  星安果 

## 1. 前言


大家好,我是安果!


关于 Python 数据处理,之前有写过一系列文章


[最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇)](http://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247486468&idx=2&sn=7c8cdfb478e5801496dad8b0ddf2061e&chksm=fc1b72c4cb6cfbd2e71861ddb8aa5d6c2ba3d4266ede047cfaf0558e6cd4e5b05a9ecca4dcdc&scene=21#wechat_redirect)


[最全总结 | 聊聊 Python 数据处理全家桶(Sqlite篇)](http://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247486487&idx=1&sn=78b344b45366c4b8ffd195b2ce300191&chksm=fc1b72d7cb6cfbc106f1a820db3d0f7ee07f22f0a7af0525952fb82a9ed87ef00675a2c18b3a&scene=21#wechat_redirect)


[最全总结 | 聊聊 Python 数据处理全家桶(MongoDB 篇)](http://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247486582&idx=2&sn=a1ec46619e543046994823d82df48dd7&chksm=fc1b72b6cb6cfba0a875a4931f4ce482307725076c285c6a3210a0e75b8082041ea17ae7abab&scene=21#wechat_redirect)


[最全总结 | 聊聊 Python 数据处理全家桶(Redis篇)](http://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247486517&idx=1&sn=01d43b1cd83c7caef94f06614fd42c02&chksm=fc1b72f5cb6cfbe39cef5a63b64c332c6b9cd2e329cc4373a72d460ca84d44e7637d5c6ae06b&scene=21#wechat_redirect)


[最全总结 | 聊聊 Python 数据处理全家桶(Memcached篇)](http://mp.weixin.qq.com/s?__biz=MzU1OTI0NjI1NQ==&mid=2247486553&idx=1&sn=06c97f43e68be307a6826e74ec126f29&chksm=fc1b7299cb6cfb8f8a6e99598327c240f9147dffeb79627d8848d465727ae8c3081e818b204d&scene=21#wechat_redirect)


如果项目涉及复杂的 SQL 处理,就可以将这些操作封装成「 存储过程 」,公开入参及出参,方便直接调用


本篇文章将聊聊如何使用 Python 执行存储过程 


## 2\. 存储过程


存储过程,全称为「 Stored Procedure 」


可以将它看成一个接口,内部会封装一些常用的操作,可以直接进行调用


存储过程的常见操作如下: 


2-1  管理存储过程


*   创建


*   查询


*   删除


```
# 1、创建一个存储过程
# 存储过程名称为:xag
delimiter $
create procedure xag()
begin
...
end $


# 2.1 通过数据库名查询所有存储过程
# 比如:数据库名为xag
select `name` from mysql.proc where db = 'xag' and `type` = 'PROCEDURE';


# 2.2 查询存储过程中状态信息
show procedure status;


# 3.通过存储过程名称,删除一个存储过程
DROP PROCEDURE  IF EXISTS xag;
```


其中


使用「 create procedure 存储过程名称 」创建一个存储过程,接着在 begin 和 end 之间编写具体的操作逻辑


2-2  变量定义及赋值


使用关键字「 declare」可以定义一个变量 


```
# 变量定义
# 比如:定义一个变量name,类型为字符串
# 默认值为 null
...
declare name varchar(255) default null;
...
```


给变量赋值有 2 种方式:普通 set 语法、select into 语法


其中


*   set 语法可以通过表达式设置变量的值


*   select into 语法是通过查询数据库表,将查询结果设置到变量中


```
# 变量定义
declare name varchar(255) default null;


# 变量赋值
# set语法
set name = 'xag';


# select into语法
# 查询name_table表中的第一条记录中的name值,保存到name变量中
select name into name from name_table limit 1;
```


2-3  条件判断 if


比如,通过年龄判断年级( if 语句)


```
...
declare age int default 23;
declare grade varchar(255) default null;


# if语句
if age <=5 then
set grade = '幼儿园';
elseif age >= 6 and age < 12 then
set grade = '小学';
elseif age >=12 and age < 15 then
set grade = '初中';
elseif age >=15 and age < 18 then
set grade = '高中';
elseif age >=18 then
set grade = '其他';
end if;
...
```


2-4  循环 while


比如,计算 1-10 数值的和,设置到变量 total 上


```
...
# 总和
declare total int default 0;


# 结束值
declare end_number int default 10;


# 临时值
declare temp int default 0;


# while循环
while temp <= end_number do
# 设置值
set total = total + temp;
set temp = temp + 1;
end while;
...
```


2-5  入参和出参


为了使编写的存储过程更加实用,我们需要在常见存储过程时,设置出参和入参


语法格式如下:


```
# 创建一个存储过程
create procedure proce_name([in/out/inout] 参数名 参数类型)
```


其中


*   默认传入值为入参,即 in


*   out 代表出参,作为返回值返回


*   如果设置为 inout,则代表既能作为出参,也可以作为入参


## 3. 实战一下


使用 Python 调用存储过程非常方便


首先,我们编写一个存储过程


比如,我这里定义了一个存储过程,传入两个入参和一个出参,将两个入参的乘积作为出参返回 


```
# 定义一个存储过程
delimiter $
create procedure num_multi(in num1 int,in num2 int,out multiply_result int)
begin
# 两个入参相乘,然后设置到出参中去
set multiply_result = num1 * num2;
end $
```


然后,在数据库中进行调用测试


使用关键字「 call 」调用存储过程,使用 select 查看返回值


```
# 调用存储过程
call num_multi(1,3,@multiply_result);
select @multiply_result;
```


接着,利用数据库配置信息创建连接及游标对象


```
import pymysql


PY_MYSQL_CONN_DICT = {
    "host": '127.0.0.1',
    "port": 3306,
    "user": 'root',
    "passwd": 'root',
    "db": 'test_db'
}


# 数据库连接
db_conn = pymysql.connect(**PY_MYSQL_CONN_DICT)


# 游标
db_cursor = db_conn.cursor(cursor=pymysql.cursors.DictCursor)
```


最后,使用函数「 callproc 」调用存储过程名称及所有参数,获取返回值


在执行完存储过程后,需要通过游标对象的「 execute 」函数获取出参及入参


```
db_cursor.callproc('num_multi', args=(3, 6, -1))


# 获取入参及出参
db_cursor.execute('SELECT @_num_multi_0, @_num_multi_1, @_num_multi_2')
# 出参值
output_result = db_cursor.fetchone()['@_num_multi_2']


# 出参值
print(output_result)
```


需要注意的是,如果存储过程涉及到更新、新增等操作,需要显式调用 commit() 函数,才会真正提交到数据库中


## 4. 最后


上面仅仅罗列出存储过程的常见语法,包含 case 条件分支处理、repeat 和 loop 循环可以自己去扩展学习


如果你觉得文章还不错,请大家 **点赞、分享、留言** 下,因为这将是我持续输出更多优质文章的最强动力!
166°/1663 人阅读/0 条评论 发表评论

登录 后发表评论