SQL 存储过程 procedure 讲解+代码实例

1. 存储过程和函数在实际项目中的使用

存储过程和函数是SQL中非常实用的功能,它们可以大量简化SQL代码和优化SQL效率,但是在实际项目中应该尽量少用存储过程和函数

理由如下:

  1. 移植性差。例如在MySQL中的存储过程移植到SQL Sever上就不一定可以用了。
  2. 调试麻烦。目前没有专门为SQL开发的用于调试的IDE,无法像VS和Eclipse一样有明确的报错提示。
  3. 扩展性不高。存储过程是一种面向过程的方法,面对复杂的业务逻辑,过程化的处理会很吃力。

所以在大型项目中应该尽量少使用甚至不使用存储过程和函数。

2. 存储过程与函数的比较

2.1. 共同点

  1. 调用时,只需要提供存储过程名或者函数名,以及参数信息,而无需将SQL语句发送到服务器,节省了网络开销。
  2. 可以重复使用。减少数据库开发人员和应用程序开发人员的工作量。
  3. 可以增强数据的安全访问控制。可以设定用户的执行权限。

2.2. 不同点

  1. 函数必须有且仅有一个返回值,且必须指定返回值数据类型(字符串/数值)。存储过程可以没有返回值,也可以有返回值,甚至可以有多个返回值,且所有的返回值需要使用out或者inout参数定义。
  2. 函数体内可以使用select into语句为某个变量赋值,但不能使用select语句返回结果或结果集。存储过程则没有这方面的限制,存储过程甚至可以返回多个结果集。
  3. 函数可以直接嵌入到SQL语句中,而且函数可以用于扩展标准的SQL语句。存储过程一般需要单独调用,并不会嵌入到SQL语句中使用,调用时需要使用call关键字。
  4. 函数中的函数体限制比较多,比如函数体内不能使用打开、开始或结束事务的语句,如start transaction、commit、rollback或者set autocommit=0等语句,不能在函数体内使用预处理SQL语句。存储过程的限制相对就比较少,基本上所有的SQL语句或MySQL命令都可以在存储过程中使用。
  5. 应用程序调用函数时,通常将函数添加到SQL语句中进行调用。应用程序调用存储过程时,必须使用call关键字进行调用,如果应用程序希望获取存储过程的返回值,就必须给存储过程的out参数或者inout参数传递SQL会话变量,才能通过该会话变量获取存储过程的返回值。

3. 变量的定义和使用

3.1. 变量的定义

3.1.1. 定义局部变量 declare

关键字declare用于在存储过程或者函数的begin end内部定义一个局部变量,作用范围在begin到end语句块之间。

语法如下:

declare [变量名1],[变量名2],...,[变量名n] [数据类型] [default [默认值]];

如语法所示,在declare关键字后面要指定变量名。变量名要注意尽量别使用关键字,不然容易出错。
指定变量的数据类型及其大小,变量可以用任何MySQL的数据类型,如int,varchar, datatime等。
定义出的变量初始值为Null,可以通过使用default关键字为变量指定默认值。

例如:

create procedure test(in i int)
begin
	declare username varchar(20); -- 定义了一个varchar类型的局部变量username
	declare adate, another date; -- 定义了两个data类型的局部变量username
  	declare total integer default 0; -- 定义一个varchar类型的局部变量username
end
3.1.2. 定义全局变量 set @

定义全局变量可以使用set语句,语法如下:

set @[变量名] = [];

定义全局变量时,sql会自动判断值类型,这种变量要在变量名称前面加上“@”符号,表示一个会话变量,在会话的整个生命周期结束之前它都是有作用的。

例如:

set @var = 7; -- 定义一个值为7的全局变量var
set @username = '西瓜'; -- 定义一个值为'西瓜'的全局变量username
3.1.3. 修改变量的值 set

set关键字用于修改变量的值,例如:

create procedure test24(in i int)
begin
	declare total integer default 0; -- 定义局部变量total,初始化为0;
	set @var = 5; -- 定义全局变量var,初始化为7
	
	set total = 1; -- 将局部变量total的值修改为1
	set @var = 25; -- 将全局变量var的值修改为3
end

4. 存储过程 Stored Procedure

4.1. 存储过程概述

存储过程是一种在数据库中存储复杂程序,以便外部程序调用的数据库对象。

存储过程经编译创建并保存在数据库中,用户可通过指定存储过程的名字和给定参数来调用执行。存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。

作个形象的比喻,存储过程也可以看作是一个"加工厂",它接收"原料"(in参数)然后将这些原料加工处理成"产品"(out/inout参数),再把"产品"交付给"调用者"。

4.1.1. 存储过程的优点
  1. 减少网络流量的使用
  2. 将重复性很高的一系列操作,封装到一个存储过程中,简化了SQL的调用
  3. 批量处理: 通过循环减少流量,也就是“跑批”
  4. 统一接口,确保数据安全。
4.1.2. 存储过程的缺点
  1. 存储过程往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
  2. 存储过程的性能调校与撰写受限于具体的数据库系统。

4.2. 创建存储过程 create procedure

创建存储过程的语法如下:

create
	[definer = {user|current_user} ]
procedure [过程名] ( [参数1],[参数2],...,[参数n] )
	[[特征1],[特征2],...,[特征n]] 
	[SQL代码];

-- definer 用于指定存储过程由哪个用户定义,默认是当前用户,注意不是指定存储过程的使用权限

-- [过程名] 该过程名用于指定存储过程,分别用户调用

-- [参数] 参数的形式为:[in|out|inout] [参数名] [参数类型],例如:in pcd_id int、inout pcd_username varchar(3)
-- -- -- in 表示该参数为输入参数,即调用时传入
-- -- -- out 表示该参数为输出参数,即存储过程的返回值
-- -- -- inout 表示该参数即可输入也可输出
-- -- -- 参数类型 可以是 int或者varchar()

-- [特征] 特征是存储过程的属性,它包括了如下几个可选特征
-- -- -- comment '' 注释信息,例如:commet '这是一个存储过程'
-- -- -- language sql 指定存储过程使用的语言为sql
-- -- -- [not] deterministic 是否指定一个输入仅对应一个输出(映射),包含下面2个可选参数
-- -- -- -- -- not deterministic(默认),表示不指定映射关系;
-- -- -- -- -- deterministic,表示指定映射关系
-- -- -- [contains sql | no sql | reads sql data | modifies sql data] 明确子程序对数据的操作,包含下面4个可选参数
-- -- -- -- -- contains sql(默认),表示子程序不包含读或者写数据的语句
-- -- -- -- -- no sql,表示子程序不包含sql
-- -- -- -- -- reads sql data,表示子程序包含读数据的语句,但是不包含写数据的语句
-- -- -- -- -- modifies sql data,表示子程序包含写数据的语句
-- -- -- sql security [definer|invoker] 指定调用权限,包含下面两个可选参数
-- -- -- -- -- sql security definer(默认),使用创建者权限调用存储过程,不受限制
-- -- -- -- -- sql security invoker,使用调用者权限调用存储过程,只有被赋予权限的调用者才能调用

例如:

-- 将tab_sale表中sale_name字段值等于传入参数的记录删除
create procedure delete_sale(in pcd_sale_name varchar(3))
delete from tab_table
where tab_table.sale_name= pcd_sale_name ;
4.2.1. 参数 in、out、inout

下面三段代码是对存储过程的参数in、out和inout的代码说明:

-- 创建一个存储过程,参数为in
create procedure test(in i int)
begin
	select i; -- 返回结果i,i=1
	set i=2;
	select i; -- 返回结果i,i=2
end

-- 调用存储过程test,并传入一个参数i=1
set @i = 1; -- 定义全局变量i
call test(@i);
select @i; -- 返回结果i,i=1

-- 由以上代码可知当存储过程的参数为in时,会传入变量的值,并且存储过程内部的赋值不会影响到外部传入的变量
-- 创建一个存储过程,参数为out
create procedure test(out i int)
begin
	select i; -- 返回结果i,i=Null
	set i=2;
	select i; -- 返回结果i,i=2
end

-- 调用存储过程test,并传入一个参数i=1
set @i=1; -- 定义全局变量i
call test(@i);
select @i; -- 返回结果i,i=2

-- 由以上代码可知当存储过程的参数为out时,变量的值不会被传入,并且存储过程内部的赋值运算可以影响到外部传入的变量
-- 创建一个存储过程,参数为inout
create procedure test(inout i int)
begin
	select i; -- 返回结果i,i=1
	set i=2;
	select i; -- 返回结果i,i=2
end

-- 调用存储过程test,并传入一个参数i=1
set @i=1; -- 定义全局变量i
call test6(@i);
select @i; -- 返回结果i,i=2

-- 由以上代码可知当存储过程的参数为out时,会传入变量的值,并且存储过程内部的赋值运算可以影响到外部传入的变量

4.3. 调用存储过程 call

存储过程的调用使用call关键字
例如:

-- 将tab_sale表中sale_name字段值等于'辣条'的记录删除
create procedure delete_sale(in pcd_sale_name varchar(3))
delete from tab_table
where tab_table.sale_name= pcd_sale_name ;

-- 调用存储过程delete_sale
call delete_sale('辣条');

4.4. 查看存储过程

4.4.1. 查看存储过程的状态

语法如下:

show procedure status like '[状态名]';

[状态名]可以查看博客:show status 查看各种状态

例如:

--查看查询时间超过long_query_time秒的查询的个数。
show procedure status like 'slow_queries';
4.4.2. 查看存储过程的定义

语法如下:

show create procedure '[过程名]'

例如:

-- 查看存储过程delete_sale的定义
show create procedure delete_sale

结果如下:

Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
delete_sale ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root@localhostPROCEDUREdelete_sale`(in pcd_num int) delete from tab_sale where tab_sale.num = pcd_num utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci
4.4.2. 从information_schema.Routines表查看存储过程的信息 mysql

MySQL数据库的所有存储过程的信息都保存在information_ schema数据库中的routines表中,因此可以使用select语句查询存储过程的相关信息。

语法为:

select * from information_schema.ROUTINES
where routine_name='[过程名]'

例如下面的SQL语句是查看存储过程delete_sale相关信息的语句。

select * from information_schema.ROUTINES
where routine_name='delete_sale'

执行结果如下:

SPECIFIC_NAME ROUTINE_CATALOG ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE DATA_TYPE
delete_sale def sqlcourse4 delete_sale PROCEDURE

4.5. 修改存储过程 alter procedure

修改存储过程的特性可以使用alter procedure关键字,语法如下:

alter procedure [存储过程名] [特性]

例如:

-- 修改存储过程delete_sale,使它可以写数据(modifies sql data)
alter procedure delete_sale modifies sql data;

4.6. 删除存储过程 drop procedure

语法:

drop procedure [if exists] [存储过程名]

例如:

-- 如果存储过程delete_sale存在,则删除它
drop procedure if exists delete_sale;
发布了223 篇原创文章 · 获赞 1092 · 访问量 142万+

猜你喜欢

转载自blog.csdn.net/baishuiniyaonulia/article/details/105378977
今日推荐