数据库存储过程讲解与实例
目录
1 存储过程简介
2 存储过程使用
2.1 创建存储过程
2.2 in,out以及inout
1 存储过程简介
SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。
优点
- 存储过程可封装,并隐藏复杂的商业逻辑。
- 存储过程可以回传值,并可以接受参数。
- 存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。
- 存储过程可以用在数据检验,强制实行商业逻辑等。
缺点
- 存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
- 存储过程的性能调校与撰写,受限于各种数据库系统。
2 存储过程使用
存储过程的一些基本语法:
--------------创建存储过程-----------------CREATE PROC [ EDURE ] procedure_name [ ; number ][ { @parameter data_type }[ VARYING ] [ = default ] [ OUTPUT ]] [ ,...n ][ WITH{ RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ][ FOR REPLICATION ]AS sql_statement [ ...n ]--------------调用存储过程-----------------EXECUTE Procedure_name '' --存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value--------------删除存储过程-----------------drop procedure procedure_name --在存储过程中能调用另外一个存储过程,而不能删除另外一个存储过程
创建存储过程的参数:
1.procedure_name :存储过程的名称,在前面加#为局部临时存储过程,加##为全局临时存储过程。
2.; number:是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。
3.@parameter: 存储过程的参数。可以有一个或多个。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2.100 个参数。
使用 @ 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。有关更多信息,请参见 EXECUTE。
4.data_type:参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。有关 SQL Server 提供的数据类型及其语法的更多信息,请参见数据类型。
说明 对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。
5.VARYING: 指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。
6.default: 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。
7.OUTPUT :表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。
8.RECOMPILE: 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。
9.ENCRYPTION: 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。 说明 在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。
10.FOR REPLICATION :指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。
11.AS :指定过程要执行的操作。
12.sql_statement :过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。
2.1 创建存储过程
UserAccount | ||||
UserID | UserName | PassWord | RegisterTime | RegisterIP |
12 | 6 | 6 | 2012-12-31 | 6 |
18 | 5 | 5 | 2013-01-01 | 5 |
19 | 1 | 1 | 2013-01-01 | 1 |
20 | 2 | 2 | 2013-01-01 | 2 |
21 | 3 | 3 | 2013-01-01 | 3 |
22 | 4 | 4 | 2013-01-01 | 4 |
23 | 5 | 5 | 2013-01-01 | 5 |
25 | 7 | 7 | 2013-01-01 | 7 |
26 | 8 | 8 | 2013-01-01 | 8 |
NULL | NULL | NULL | NULL | NULL |
针对上面的表,我使用存储过程对它做一些操作:
1. 只返回单一记录集的存储过程
-------------创建名为GetUserAccount的存储过程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go-------------执行上面的存储过程----------------
exec GetUserAccount
结果:相当于运行 select * from UserAccount 这行代码,结果为整个表的数据。
2.没有输入输出的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure inUserAccount
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9)
go-------------执行上面的存储过程----------------exec inUserAccount
结果:相当于运行 insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9) 这行代码。
3.有返回值的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure inUserAccountRe
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10)
return @@rowcount
go-------------执行上面的存储过程----------------exec inUserAccountRe
解释:这里的@@rowcount为执行存储过程影响的行数,执行的结果是不仅插入了一条数据,还返回了一个值即 return value =1 ,这个可以在程序中获取,稍后在c#调用存储过程中会有说到。
4.有输入参数和输出参数的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure GetUserAccountRe
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
go-------------执行上面的存储过程----------------exec GetUserAccountRe '7',null
解释:@UserName为输入参数,@UserID为输出参数。 运行结果为@userID为COOUT(*)即 =1。
5. 同时具有返回值、输入参数、输出参数的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure GetUserAccountRe1
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
return @@rowcount
go-------------执行上面的存储过程----------------exec GetUserAccountRe1 '7',null
结果:@userID为COOUT(*)即 =1,Retun Value=1。
6.同时返回参数和记录集的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure GetUserAccountRe2
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
select * from UserAccount
return @@rowcount
go-------------执行上面的存储过程----------------exec GetUserAccountRe2 '7',null
结果:返回执行 select * from UserAccount 这句代码的结果集,同时@userID为COOUT(*)即 =1,Retun Value=9。
7.返回多个记录集的存储过程
-------------创建名为GetUserAccount的存储过程----------------create Procedure GetUserAccountRe3
as
select * from UserAccount
select * from UserAccount where UserID>5
go-------------执行上面的存储过程----------------exec GetUserAccountRe3
结果:返回两个结果集,一个为 select * from UserAccount,另一个为 select * from UserAccount where UserID>5 。
2.2 in,out以及inout
MySQL存储过程的参数用在存储过程的定义,共有三种参数类型
IN,OUT,INOUT
格式为:Create procedure|function([[IN |OUT |INOUT ] 参数名 数据类形...])
IN 输入参数
表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
OUT 输出参数
该值可在存储过程内部被改变,并可返回
INOUT 输入输出参数
调用时指定,并且可被改变和返回
1.参数in的使用(代表输入,意思说你的参数要传到存过过程的过程里面去)
//为了避免存储过程中分号(";")结束语句,我们使用分隔符告诉mysql解释器,该段命令是否已经结束了。
/**
案例功能:求1-n的和
*/delimiter $
create procedure p1(in n int)
begin
declare total int default 0;
declare num int default 0;
while num < n do
set num:=num+1;
set total:=total+num;
end while;
select total;
end$call p1(10)$
创建并执行完存储过程,运行结果如下:
2.参数out的使用(代表往外输出)
//这里还要注意一点的就是我们的输出参数一定要设置相应类型的初始,否则不管你怎么计算得出的结果都为NULL值
/**
案例功能:求1-n的和
*/create procedure p2(in n int,out total int)
begin
declare num int default 0;
set total:=0;
while num < n do
set num:=num+1;
set total:=total+num;
end while;
end$
注意:对于第一个输入参数我们可以理解,但是第二个输出参数我们到底应该怎么输?
这里我们需要对第二个参数定义一个变量名(更形象点就是你输入一个输入类型的参数n,由输出参数total往外发射输出我们只需要定义一个变量名来接收这个输出值即可)
call p2(100,@sum)$//这里的@sum就是我定义用来接收处处total的值
select @sum$
创建并执行完存储过程(查询定义的变量值),运行结果如下:
总结in、out区别:
in:表示输入一个值,你需要一个值,我给你一个值
out:你往外输出一个值,你输出的那个值我就拿一个变量来接收你给我输出的那个值
3.参数inout的使用(既能输入一个值又能传出来一个值)
/**
功能:传一个年龄,自动让年龄增长10岁
*/
create procedure p3(inout age int)
begin
set age:=age+10;
end$
注意:调用的时候,我这里需要和大家声明一下,inout型的参数值既是输入类型又是输出类型,你给它一个值,值不是变量,不是变量那out的时候它怎么赋给这个值是不是?
因此我们需要先设置一个变量并初始化这个值,调用的时候直接传这个变量即可。
set @currentAge=8$
call p3(@currentAge)$
select @currentAge$
创建并执行完存储过程,运行结果如下:
使用参数的存储过程(备注:decimal(8,2)意思就是总共有8位,小数点后留两位)
create procedure procedureName( out min decimal(8,2), out avg decimal(8,2), out max decimal(8,2)
)
BEGIN select MIN(price) INTO min from order; select AVG(price) into avg from order; select MAX(price) into max from order;
END;
此过程接受三个参数, 分别用于获取订单表的最小、平均、最大价格。每个参数必须具有指定的类
型,这里使用十进制值(decimal(8,2)), 关键字OUT指出相应的参数用来从存储过程传出
一个值(返回给调用者)
MySQL支持IN(传递给存储过程)、OUT(从存储过程传出,如这里所用)和INOUT(对存储过程传入和传出)类型的参数。存储过程的代码位于BEGIN和END语句内,如前所见,它们是一系列SELECT语句,用来检索值,然后保存到相应的变量(通过指定INTO关键字)
为调用此修改过的存储过程,必须指定3个变量名,如下所示:(所有MySQL变量都必须以@开始。)
-- 由于过程指定三个参数, 故调用必须要参数匹配
call procedureName(@min, @avg, @max);
该调用并没有任何输出, 只是把调用的结果赋给了调用时传入的变量(@min, @avg, @max)。然后即可调用显示该变量的值。
select @min, @avg, @max;
结果如下
@min | @avg | @max |
42.00 | 601.00 | 2222.00 |
使用in参数, 输入一个用户id, 返回该用户所有订单的总价格。
create procedure getTotalById ( in userId int, out total decimal(8,2)
)
BEGIN select SUM(r.price) from order r where r.u_id = userId into total;
END;
调用存储过程
call getTotalById(1, @total); select @total;
结果将返回该用户所有订单的合计价格。
复杂一点的过程, 根据用户id获取该用户的所有订单价格, 并动态的选择是否加税。代码设计如下
create procedure getTotalByUser2( in userId int, in flag boolean, -- 是否加税标记 out total decimal(8,2)
)
begin DECLARE tmptotal DECIMAL(8,2); DECLARE taxrate int DEFAULT 6;-- 默认的加税的利率 select SUM(r.price) from order r where r.u_id = userId into tmptotal; if flag then select tmptotal + (tmptotal/1000*taxrate) into tmptotal; end if; select tmptotal into total;
END;
该过程传入三个参数, 用户id, 是否加税以及返回的总价格,在过程内部, 定义两个局部变量tmptotal和taxrate,把查询出来的结果赋给临时变量, 在判断是否加税。最后把局部变量的值赋给输出参数。
call getTotalByUser2(1, false, @total); -- 不加税
call getTotalByUser2(1, true, @total); -- 加税
select @total;
数据库存储过程讲解与实例相关推荐
- MySQL数据库存储过程讲解与实例
存储过程简介 SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储 ...
- Mysql数据库存储过程基本语法讲解
Mysql数据库存储过程基本语法讲解 一般情况下MYSQL以:结尾表示确认输入并执行语句,但在存储过程中:不是表示结束,因此可以用该命令将:号改为//表示确认输入并执行.存储过程如同一门程序设计语言, ...
- SQL 存储过程 procedure 讲解+代码实例
文章目录 1. 存储过程概述 2. 创建存储过程 create procedure 2.1. 参数 in.out.inout 3. 调用存储过程 call 4. 查看存储过程 4.1. 查看存储过程的 ...
- SAP AMDP数据库存储过程,AMDP语法实例
目录 AMDP介绍 AMDP语法 DECLARE变量声明 CURSOR循环(FOR) 数组的使用 IF...ELSE 内表读取 方法嵌套调用 AMDP function,AMDP函数实现 AMDP p ...
- SQL 函数 function 讲解+代码实例
文章目录 1. 对存储程序的说明 2. 创建函数 create function 3. 调用函数 select 4. 查看函数 4.1. 查看函数状态 show status 4.2. 查看函数定义 ...
- mysql数据库存储过程及调用方法
mysql数据库存储过程及调用方法 mysql5.0以后就支持存储过程了,目前mysql的6.0Alpha版也已经推出.6.0不仅支持大型数据库如oracle等的绝大部分功 能,如存储过程.视图.触发 ...
- 转载:mysql存储过程讲解
记录MYSQL存储过程中的关键语法: DELIMITER // 声明语句结束符,用于区分; CEATE PROCEDURE demo_in_parameter(IN p_in int) 声明存储过程 ...
- 易语言 存储过程 mysql_在易语言中调用MS SQL SERVER数据库存储过程(Transact-SQL)方法总结...
作者:liigo 日期:2010/8/25 Microsoft SQL SERVER 数据库存储过程,根据其输入输出数据,笼统的可以分为以下几种情况或其组合:无输入,有一个或多个输入参数,无输出,直接 ...
- SQL Server数据库存储过程——以自定义存储过程为例
SQL Server数据库存储过程--以自定义存储过程为例 1.什么是数据库存储过程 存储过程就是预编译SQL语句的集合,这些语句存储在一个名称下并作为一个单元处理.存储过程代替了传统的逐条执行SQL ...
- 数据库存储过程与存储函数
数据库存储过程与存储函数_伱糸淂忄-CSDN博客 MySQL数据库之存储过程与存储函数 - 奥辰 - 博客园 1.数据库存储过程与存储函数 存储过程是一组为了完成特定功能的SQL语句集,经过编译后存储 ...
最新文章
- Python3--自动化办公
- 跳槽9招让你“空降”任何企业都能成功
- python tab和空格混用_Python编程常见十大错误,看完你自己都笑了!
- 【算法分析与设计】实验 回溯算法解决0-1背包问题
- 一個便宜的高负载网站架构
- dj鲜生-19-登陆功能-利用内置认证体系
- MAC安装influxdb和grafana
- 三星电子预计第四季度营业利润为9万亿韩元 低于分析师预期
- Java教程:Java JDK环境变量配置
- Android线程和线程Handler基础一览
- 输入url后的加载过程
- 【python爬虫】第11章——scrapy框架持久化存储
- 微信小程序wx.setClipboardData复制文本
- python爬虫——爬取小说
- 骗术一览,大猫小猫都小心了!【转载】
- Vim编辑完如何保存退出
- 服务注册中心:Eureka
- 操作系统期末复习-第一章:操作系统概论
- LinuxGit Accumulation
- 今年9月开学!香港科技大学(广州)人工智能专业已开始招生!