什么是存储过程?
存储过程可以说是一个记录集吧,它是由一些SQL语句组成的代码块,这些SQL语句代码实现一些功能(对单表或多表的增删改查),
然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。
存储在数据库中经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。
存储过程说白了就是一堆 SQL 的合并。中间加了点逻辑控制。
但是存储过程处理比较复杂的业务时比较实用。
比如说,一个复杂的数据操作。如果你在前台处理的话。可能会涉及到多次数据库连接。但如果你用存储过程的话。就只有一次。从响应时间上来说有优势。
也就是说存储过程可以给我们带来运行效率提高的好处。
另外,程序容易出现 BUG 不稳定,而存储过程,只要数据库不出现问题,基本上是不会出现什么问题的。也就是说从安全上讲,使用了存储过程的系统更加稳定。
那么什么时候才可以用存储过程?对于数据量不是很大以及业务处理不是很复杂的小项目就无需要了么?
错。存储过程不仅仅适用于大型项目,对于中小型项目,使用存储过程也是非常有必要的。
【优点】
1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,select,Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储过程,只需要连接一次数据库就可以了。
3.存储过程可以重复使用,可减少数据库开发人员的工作量。
4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权。
5.前端只需要传输值就可以,不用传输sql语句了.数据库自行调用储存过程,减少了网络的传输量
【缺点】
1. 运行速度:大多数高级的数据库系统都有cache的,所以编译sql的花费没什么影响。
但是执行存储过程要比直接执行sql花费更多(检查权限等),所以对于很简单的sql,存储过程没有什么优势。
2. 网络负荷:如果在存储过程中没有多次数据交互,那么实际上网络传输量和直接sql是一样的。
3. 安全机制:对于传统的C/S结构,连接数据库的用户可以不同,所以安全机制有用;
但是在web的三层架构中,数据库用户不是给用户用的,所以基本上,只有一个用户,拥有所有权限(最多还有一个开发用户)。
这个时候,安全机制有点多余。
4. 移植性:反正一般的应用总是绑定某个数据库的,不然就无法靠优化数据库访问来提高性能了。
基本原则是:所有数据访问在应用层封装为数据访问层,在那里,如果SQL简单的话,直接用SQL;
如果SQL复杂,或者数据交互多且中间数据最后不会用到,使用存储过程。其他凭经验吧。
--------------------------------------------------------------------------------------------------------
account转账表(account_id varchar2(5)帐户id,
name varchar2(10)帐户名,
sum number(10,2)帐户余额
)
SQL> create table account(account_id varchar2(5),name varchar2(10),sum number(10,2));
SQL> insert into account values('10001','tom',50000);
SQL> insert into account values('10002','kate',0);
SQL> commit;
SQL> select * from account;
模拟银行转账【参数:zc_zh 转出帐户,zr_zh 转入帐户,zz_je 转账金额】
create or replace procedure pro_zz(zc_zh in varchar2,zr_zh in varchar2,zz_je in int)
as
var_sum int:=0;
begin
select sum into var_sum from account where account_id=zc_zh;
if var_sum<zz_je then
dbms_output.put_line('钱不够了!');
else
update account set sum=sum-zz_je where account_id=zc_zh;
dbms_output.put_line('转出成功!');
update account set sum=sum+zz_je where account_id=zr_zh;
dbms_output.put_line('转入成功!');
commit;
end if;
end;
/
SQL> set serveroutput on 【显示过程】
SQL> exec pro_zz('10002','10001',10000);
SQL> exec pro_zz('10001','10002',10000);
SQL> select * from account;(tom少10000,kate多10000)
jy交易记录表(zc_id varchar2(10)转出id,
zr_id varchar2(10)转入id,
je number(10,2)交易余额
)
SQL> create table jy(zc_id varchar2(10),zr_id varchar2(10),je number(10,2));
模拟出:帐户转出总金额有限制,转出总金额超过2w,不让转帐
【参数:zc_zh 转出帐户,zr_zh 转入帐户,zz_je 转账金额】
create or replace procedure pro_zz(zc_zh in varchar2,zr_zh in varchar2,zz_je in int)
as
var_sum int:=0;
var_vvv int:=0;
begin
select sum into var_sum from account where account_id=zc_zh;
if var_sum<zz_je then
dbms_output.put_line('钱不够了!');
else
update account set sum=sum-zz_je where account_id=zc_zh;
dbms_output.put_line('转出成功!');
update account set sum=sum+zz_je where account_id=zr_zh;
dbms_output.put_line('转入成功!');
insert into jy (zc_id,zr_id,je)values(zc_zh,zr_zh,zz_je);
end if;
select sum(je) into var_vvv from jy where zc_id=zc_zh;
if
var_vvv > 20000 then
dbms_output.put_line('转帐总金额太多了,此次转帐失败');
rollback;
else
dbms_output.put_line('所有操作成功!!!!!');
commit;
end if;
end;
/
SQL> set serveroutput on 【显示过程】
SQL> exec pro_zz('10001','10002',10000);
SQL> select * from account;
SQL> select * from jy;
是既需要传入参数,也用来传出值
create or replace procedure swap(p1 in out number,p2 in out number)
is
v_temp number;
begin
v_temp:=p1;
p1:=p2;
p2:=v_temp;
end;
/
调用带IN OUT参数的过程:
declare
num1 number:=100;
num2 number:=200;
begin
swap(num1,num2);
dbms_output.put_line('num1= '||num1);
dbms_output.put_line('num2= '||num2);
end;
/
其中num1,num2传入到p1,p2,
p1=100;
p2=200;
然后调用procedure后,p1=200,p1=100
这些值也同时输出