四时宝库

程序员的知识宝库

14、MySQL存储过程

存储过程

存储过程的概念

系统存储过程

存储过程的管理

语法结构

存储过程的创建过程

简单示例

结合pymysql实现示例

带参数的存储过程

存储过程生成全局变量以便引用

局部变量的定义

全局变量的定义

存储过程的输入IN参数定义

存储过程的输出OUT参数定义

存储过程的输入输出INOUT参数定义

存储过程

它是给一大堆的SQL语句起的一个别名,以后我们就可以使用这个别名去操作了,所以就这样来说,存储过程是保存在mysql上的一个别名,别名代指的是一大堆是SQL语句,有了它之后我们就不需要再去写SQL语句了,只要使用这个别名就能查到结果;

Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用。当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句。这样就可以提高存储过程的性能;

存储过程的概念

存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。

存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数、输出参数、返回单个或多个结果集以及返回值。

由于存储过程在创建时即在数据库服务器上进行了编译并存储在数据库中,所以存储过程运行要比单个的SQL语句块要快。同时由于在调用时只需用提供存储过程名和必要的参数信息,所以在一定程度上也可以减少网络流量、简单网络负担。

1、 存储过程的优点

A、 存储过程允许标准组件式编程存储过程创建后可以在程序中被多次调用执行,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,但对应用程序源代码却毫无影响,从而极大的提高了程序的可移植性。

B、 存储过程能够实现较快的执行速度如果某一操作包含大量的T-SQL语句代码,分别被多次执行,那么存储过程要比批处理的执行速度快得多。因为存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析、优化,并给出最终被存在系统表中的存储计划。而批处理的T-SQL语句每次运行都需要预编译和优化,所以速度就要慢一些。

C、 存储过程减轻网络流量对于同一个针对数据库对象的操作,如果这一操作所涉及到的T-SQL语句被组织成一存储过程,那么当在客户机上调用该存储过程时,网络中传递的只是该调用语句,否则将会是多条SQL语句。从而减轻了网络流量,降低了网络负载。

D、 存储过程可被作为一种安全机制来充分利用系统管理员可以对执行的某一个存储过程进行权限限制,从而能够实现对某些数据访问的限制,避免非授权用户对数据的访问,保证数据的安全。

系统存储过程

系统存储过程是系统创建的存储过程,目的在于能够方便的从系统表中查询信息或完成与更新数据库表相关的管理任务或其他的系统管理任务。系统存储过程主要存储在master数据库中,以“sp”下划线开头的存储过程。尽管这些系统存储过程在master数据库中,但我们在其他数据库还是可以调用系统存储过程。有一些系统存储过程会在创建新的数据库的时候被自动创建在当前数据库中。

存储过程的管理

查看存储过程: show procedure status where db='db_name';

查看当前数据库下面的存储过程:select specific_name from mysql.proc;

查看存储过程的内容:select specific_name,body from mysql.proc;

查看存过过程的内容:show create procedure 'pro_name'

修改使用alter

语法结构

create proc | procedure pro_name

[{@参数数据类型} [=默认值] [output],

{@参数数据类型} [=默认值] [output],

....

]

as

SQL_statements

存储过程的创建过程

选中数据库->改变结束符号->创建存储过程;

示例如下:

# 创建

drop procedure if exists cce;

delimiter $

create procedure cce()

begin

select * from cce limit 2;

end

$

delimiter ;

# 执行

[cce]>call cce;

+----+------+--------+----------------+

| id | name | gender | email |

+----+------+--------+----------------+

| 1 | 7cnI | M | LJPoGa@163.com |

| 2 | UyKq | M | MZgJwL@163.com |

+----+------+--------+----------------+

简单示例

delimiter @ /*修改结束符*/

create procedure cce() /*创建存储过程*/

begin

INSERT INTO `cce`.`cce`( `time`) VALUES ( '2018-07-07 16:01:46');

select count(*) from cce;

end

@

delimiter ; /*修改结束符*/

call cce(); /*执行该存储过程*/

结合pymysql实现示例

# 创建表结构并插入测试数据

drop table if exists cce;

create table cce(id int auto_increment,name char(32) not null,age int not null,gender enum('M','F') not null default 'M',primary key(id

))engine=innodb default charset=utf8;

insert into cce(name,age,gender) values ('cce',28,'M'),('cfj',16,'F'),('csw',44,'M');

# 创建存储过程

drop procedure if exists query_cce;

delimiter @

create procedure query_cce()

begin

select * from cce where gender = 'F';

end

@

delimiter ;

测试查询

[cce]>call query_cce();

+----+------+-----+--------+

| id | name | age | gender |

+----+------+-----+--------+

| 2 | cfj | 16 | F |

+----+------+-----+--------+

1 row in set (0.01 sec)

# pymysql示例

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

from mysqldb import *

conn=pymysql.connect(host='127.0.0.1',user='root',password='',database='cce') # 指定连接的数据库

# cursor=conn.cursor() # 使用cursor()方法获取操作游标,默认以元祖的形式返回

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标, 操作数据库, 指定游标返回内容为字典类型

cursor.callproc('query_cce')

data=cursor.fetchone() # 接受结果返回的其中第一行,

cursor.close() # 关闭指针对象

conn.close() # 关闭socket连接对象

if data:

print('结果为:%s'%data)

else:

print('查询失败')

# 结果为:{'age': 16, 'gender': 'F', 'id': 2, 'name': 'cfj'}

带参数的存储过程

# 创建存储过程

drop procedure if exists query_cce;

delimiter @

create procedure query_cce(in v1 char)

begin

select * from cce where gender = v1;

end

@

delimiter ;

[cce]>call query_cce('F');

+----+------+-----+--------+

| id | name | age | gender |

+----+------+-----+--------+

| 2 | cfj | 16 | F |

+----+------+-----+--------+

1 row in set (0.01 sec)

[cce]>call query_cce('M');

+----+------+-----+--------+

| id | name | age | gender |

+----+------+-----+--------+

| 1 | cce | 28 | M |

| 3 | csw | 44 | M |

+----+------+-----+--------+

2 rows in set (0.00 sec)

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

from mysqldb import *

conn=pymysql.connect(host='127.0.0.1',user='root',password='',database='cce') # 指定连接的数据库

# cursor=conn.cursor() # 使用cursor()方法获取操作游标,默认以元祖的形式返回

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标, 操作数据库, 指定游标返回内容为字典类型

cursor.callproc('query_cce','M')

data=cursor.fetchall() # 接受结果返回的其中第一行,

cursor.close() # 关闭指针对象

conn.close() # 关闭socket连接对象

if data:

print('结果为:%s'%data)

else:

print('查询失败')

# 结果为:[{'name': 'cfj', 'gender': 'F', 'id': 2, 'age': 16}]

存储过程生成全局变量以便引用

变量的值必须只有一个,也可以结合聚合函数来实现;

# 创建存储过程,使用select into语法将结果赋值给变量

drop procedure if exists query_cce;

delimiter @@

create procedure query_cce(in v1 char)

begin

select count(1) into @result from cce where gender = v1;

end

@@

delimiter ;

# 执行存储过程

[cce]>call query_cce('M');

# 查看返回结果

[cce]>select @result;

+---------+

| @result |

+---------+

| 2 |

+---------+

1 row in set (0.00 sec)

# 执行存储过程

[cce]>call query_cce('F');

# 查看返回结果

[cce]>select @result;

+---------+

| @result |

+---------+

| 1 |

+---------+

1 row in set (0.01 sec

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

from mysqldb import *

conn=pymysql.connect(host='127.0.0.1',user='root',password='',database='cce') # 指定连接的数据库

# cursor=conn.cursor() # 使用cursor()方法获取操作游标,默认以元祖的形式返回

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标, 操作数据库, 指定游标返回内容为字典类型

cursor.callproc('query_cce','M') # 执行存储过程,如果该存储过程有打印信息如果我们需要看到该信息那么就需要fetchall一下,如果不需要看到或者没有跳过即可;

cursor.execute('select @result')# 获取全局变量

data=cursor.fetchall() # 返回的是一个列表套字典

cursor.close() # 关闭指针对象

conn.close() # 关闭socket连接对象

if data:

print('结果为:%s'%data[0]['@result'])

else:

print('查询失败')

# 结果为:2

局部变量的定义

# 创建

drop procedure if exists cce; # 如果存储过程存在那么就删除

delimiter $ # 修改结束符

create procedure cce()

begin # 开始过程

declare result int default 0; # 使用变量需要先定义变量的类型

set result=(select count(1) from cce); # 将count的结果赋值给全局部变量result

select result; # 打印出result的结果

end # 过程结束

$

delimiter ; # 改回结束符

CALL cce; # 执行存储过程

# 执行

[cce]>call cce;

+---------+

| result |

+---------+

| 1116385 |

+---------+

全局变量的定义

# 创建

drop procedure if exists cce; # 如果存储过程存在那么就删除

delimiter $ # 修改结束符

create procedure cce()

begin # 开始过程

declare result int default 0; # 使用变量需要先定义变量的类型

set @result=(select count(1) from cce); # 将count的结果赋值给全局变量result

end # 过程结束

$

delimiter ; # 改回结束符

# 执行

[cce]>call cce; # 执行存储过程

[cce]>select @result; # 获取全局变量

+---------+

| @result |

+---------+

| 1116385 |

+---------+

存储过程的输入IN参数定义

MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT,形式如:

CREATE PROCEDURE([[IN |OUT |INOUT ] 参数名 数据类形...])

IN 输入参数:表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值;

OUT 输出参数:该值可在存储过程内部被改变,并可返回;

INOUT 输入输出参数:调用时指定,并且可被改变和返回,同时具有IN和OUT的功能;

# 创建带in参数的存储过程

drop procedure if exists cce_vargs;

delimiter $

create procedure cce_vargs(in varg1 int)

begin

select varg1; # 打印局部变量

set @varg1=varg1+ 1; # set全局变量

end

$

delimiter ;

# 执行

[cce]>set @var=1;

[cce]>call cce_vargs(@var); # 执行存储过程会打印出局部变量

+-------+

| varg1 |

+-------+

| 1 |

+-------+

[cce]>select @varg1; # 查看生成的全局变量

+--------+

| @varg1 |

+--------+

| 2 |

+--------+

存储过程的输出OUT参数定义

# 示例一

drop procedure if exists cce_out;

delimiter $

create procedure cce_out(out cce_out_var int)

begin

select cce_out_var;

set cce_out_var = 10;

select cce_out_var;

end

$

delimiter ;

执行

[cce]>set @var=1;

[cce]> call cce_out(@var); # 输出参数有一个特点,即便最开始的时候给了这么一个值,它也是为NULL的,只有重新赋值之后才会变成15,只有当存储过程改变之后的值,才会发生修改

+-------------+

| cce_out_var |

+-------------+

| NULL |

+-------------+

+-------------+

| cce_out_var |

+-------------+

| 10 |

+-------------+

# 示例二

# 创建

drop procedure if exists cce_rows;

delimiter $

create procedure cce_rows(out rows int)

begin

select count(*) into rows from cce;

end

$

delimiter ;

# 执行

[cce]>set @rows=0; # 创建全局变量

[cce]>call cce_rows(@rows); # 执行存储过程,结果会保存到这个全局变量

[cce]>select @rows; # 查看结果

+---------+

| @rows |

+---------+

| 1116385 |

+---------+

存储过程的输入输出INOUT参数定义

# 创建

drop procedure if exists cce_inout;

delimiter $

create procedure cce_inout(inout var_inout int)

begin

select var_inout; # 打印传入的值

set var_inout=10; # 重新赋值

select var_inout; # 打印重新赋值的值

end

$

delimiter ;

# 执行

[cce]>set @var=0;

[cce]>call cce_inout(@var);

+-----------+

| var_inout |

+-----------+

| 0 |

+-----------+

+-----------+

| var_inout |

+-----------+

| 10 |

+-----------+

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接