话说很久很久以前,大约是我国解放很久很久以后,有位叫兔子的童鞋对存储过程很感兴趣,苦于无师,甚为烦恼。这个社会这么和谐,怎么能让一个勤奋好学的人找不到方向呢?于是乎这篇文章诞生了。。。
大家都知道,SQL语言是第四代语言(4GL),什么是第四代语言呢?谷老师,百老师和本老师都会告诉你,它是一个非过程化的语言,也就是说我们只需要告诉它做什么而不必告诉它怎么做。比如:select * from a;只要执行这个语句,a表当中所有的数据就都被查出来了==#但是,非过程化的语言处理复杂业务的时候就很困难了,为了解决这个问题,PL/SQL应运而生。。。
本文介绍的是PL/SQL程序设计当中非常重要的存储过程的基础篇,各位看官先镇定一下情绪,喝点茶,待我细细道来。。。。。。
------------------------------------华丽丽的分割线-----------------------------------------------------
下面是一个第一个存储过程,目的是实现银行的转账业务,这个事务把一笔金额从一个账户A00转到另一个账户B00中。
create table account ( ano varchar2(3) primary key, balance number(4) ); insert into account values('A00',100); insert into account values('B00',200); insert into account values('C00',300);
存储过程:
set serveroutput on; create or replace procedure account_transfer(amount in int) as var_balance int; begin /**读账户A00的余额 =>amount */ select balance INTO var_balance from account where ano='A00'; /**更改账户A00的余额,即 balance+amount =>balance */ update account set balance=balance-amount where ano='A00'; if var_balance-amount<0 THEN dbms_output.put_line('金额不足,不能转账!'); ROLLBACK; /**撤销刚才的修改,恢复事务*/ return; end if; update account set balance=balance+amount where ano='B00'; COMMIT; dbms_output.put_line('提交成功,正常转账!'); end; /
好了,第一句set serveroutput on目的是为了使得程序中dbms_output.put_line()函数能够正常输出文字,如果你觉得每次都要写这句话太麻烦的话你可以把它写到login.sql文件中,关于login.sql文件怎么配置,请关注我的第一篇博客《Myeclipse中Tomcat的配置及login.sql文件的配置》(传送门:http://blog.csdn.net/IceArmour/archive/2010/11/24/6033001.aspx)。。。
在这里,create or replace procedure 表示创建或代替一个存储过程,如果没有or replace语句,则仅仅是新建一个存储过程。如果系统存在该存储过程,则会报错。。。
amount表示的是转账的金额;in表示输入进去的转账金额数,它是按值传递的;int,额,,这个不用解释了吧。。。
在as和begin中间定义的变量表示是在以下过程块中式全局变量,begin和end表示过程处理块,这是典型的Pascal(为了纪念伟大物理学家帕斯卡,压强的那个~~~)语言写法。
select ... into ...表示把balance写到var_balance这个局部变量中进行操作。。。
运行一下,让我们看看程序的结果:
select * from account;发现A00变成了50,B00变成了250.
好了,执行成功!
问题1:若A00或B00不存在,如何修改程序实现之?
create or replace procedure account_transfer_1( amount in int )as var_balance int; userNumA int; userNumB int; begin /**验证用户A00或B00是否存在 */ select 1 into userNumA from account where ano='A00'; select 1 into userNumB from account where ano='B00'; if(userNumA = 0 or userNumB = 0) then dbms_output.put_line('A或B用户不存在!'); return; end if; /**读账户A00的余额 =>amount */ select balance INTO var_balance from account where ano='A00'; /**更改账户A00的余额,即 balance+amount =>balance */ update account set balance=balance-amount where ano='A00'; if var_balance-amount<0 THEN dbms_output.put_line('金额不足,不能转账!'); ROLLBACK; /**撤销刚才的修改,恢复事务*/ return; end if; update account set balance=balance+amount where ano='B00'; COMMIT; dbms_output.put_line('提交成功,正常转账!'); end; /
这个问题很简单吧,这里定义了userNumA和userNumB两个全局变量,验证A00或B00是否存在,让我们把account表中的全部数据delete掉再重新插入原来的数据。实验结果:
好啦,不解释了。。。
问题2:将一定额度的钱从一个帐户转帐到另一个帐户,如何修改程序实现之?
create or replace procedure account_transfer_2( userOne in account.ano%type, userTwo in account.ano%type, amount in int )as var_balance int; begin /**读账户userOne的余额 =>amount */ select balance INTO var_balance from account where ano=userOne; /**更改账户userOne的余额,即 balance+amount =>balance */ update account set balance=balance-amount where ano=userOne; if var_balance-amount<0 THEN dbms_output.put_line('金额不足,不能转账!'); ROLLBACK; /**撤销刚才的修改,恢复事务*/ return; end if; update account set balance=balance+amount where ano=userTwo; COMMIT; dbms_output.put_line('提交成功,正常转账!'); end; /
发现新情况没?这里定义了userOne和userTwo两个用户,他们是account表的ano字段,%type的意思是为了使得这个字段与account的ano字段的属性一致,当然,你也可以写成userOne in varchar2(3),和account表的ano字段属性一致就行==#
delete掉所有数据,然后重新插入原来的,执行结果:
第二次执行结果:
查询结果:
好了,本文就到这里,下篇精彩继续~~~~~~~~~