为什么一个存储过程为什么要写几个begin...end;语句??一个不就行了吗??
写几个与写一个不同吗?
比如下个过程:CREATE OR REPLACE PROCEDURE yfgl_ypkctj(
as_yfbm in varchar2, -- 药房编码、药房部门ID
al_xlh in long, --入库明细系列号
as_tjdh in varchar2 , --新调价单号
adt_now in date , --调价日期
ad_xsj in decimal, --新药库零售价
ad_sl in decimal, --库存数量
as_machine in varchar2 , --机器名
as_yy in varchar2 ,
as_czy in varchar2 , --操作员
as_bz in varchar2 , --标志
os_retmsg out varchar2, --错误信息
oi_return out integer --返回值
-- 返回值:
-- 0 --------
-- 1 --------
-- -1 --------sql语句执行失败,回滚减库存的事务
-- -2 --------非sql错误
) isifzb varchar2(1);
gmp varchar2(1);
lsdj number(16,10);
mrdj number(16,10);
ypdm varchar2(12);
ph varchar2(60);
sccj varchar2(120);
yxq date;
pkg_unit_ratio number(16,10);
dqsl number(16,10);
ykcksl number(16,10);
ykmrdj number(16,10);
yklsdj number(16,10);
rksxh long;
ykrkxlh long;
ly_seq long;
ls_rkdh varchar2(12);
min_pkg_unit varchar2(12);
pkg_unit varchar2(12);
bz varchar2(1);
item_cnname varchar2(100);
item_cnalias varchar2(100);
itempkg_id varchar2(12);
pkg_name varchar2(40);
ykrkdh varchar2(12);
ldec_lsdj number(16,10);
newyklsdj number(16,10);
ldec_rklsdj number(16,10);
begin
--取出入库明细的药品信息
begin
select rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,rklsdj
into ls_rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,ldec_rklsdj
from yfgl_t_rkmx where xlh=al_xlh;
if (pkg_unit_ratio=0 or pkg_unit_ratio is null) then
pkg_unit_ratio:=1;
end if;
if yklsdj is null then
yklsdj :=lsdj * pkg_unit_ratio;
end if;
newyklsdj :=ad_xsj;
--库存调价数量=库存数量,否则=调价数量
dqsl := ad_sl ;
if as_bz ='nt' then
--lsdj :=round(yklsdj/pkg_unit_ratio,10);
ldec_lsdj :=lsdj;
lsdj :=ad_xsj;
yklsdj :=lsdj * pkg_unit_ratio;
newyklsdj :=ldec_lsdj * pkg_unit_ratio;
end if; if as_bz ='wt' then
yklsdj :=lsdj * pkg_unit_ratio;
end if;
if as_bz ='wf' then
lsdj :=ldec_rklsdj;
yklsdj :=lsdj * pkg_unit_ratio;
end if; exception
when others then
os_retmsg := TO_CHAR(al_xlh) || '取yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
end; --if as_bz='kc' or as_bz='wt' then
if as_bz<>'nt' then
ldec_lsdj := 0;
ldec_lsdj := round(ad_xsj/pkg_unit_ratio,10);
end if ; --插调价明细yfgl_t_ypkctjmx
begin
/*
外退反悔:
旧药房零售单价:外退单的零售单价
新药房零售单价;当前库存零售单价
内退反悔:
旧药房零售单价:当前库存零售单价
新药房零售单价:内退单的零售单价
*/
insert into yfgl_t_ypkctjmx (xlh,yfbm,tjdh,ypdm,rkdh,kcsl,mrdj,oldlsdj,newlsdj,oldyklsdj,newyklsdj,tjrq,rkxlh,sccj,czy,pkg_unit_ratio,rksxh,bz,min_pkg_unit,tjyy,item_cnalias,itempkg_id,pkg_name,pkg_unit,item_cnname)
values (yfgl_yfseq.nextval,as_yfbm,as_tjdh,ypdm,ls_rkdh,dqsl,mrdj,lsdj,ldec_lsdj,yklsdj,newyklsdj,adt_now,al_xlh,sccj,as_czy,pkg_unit_ratio,rksxh,as_bz,min_pkg_unit,as_yy,item_cnalias,itempkg_id,pkg_name,pkg_unit,item_cnname);
exception
when others then
os_retmsg := TO_CHAR(al_xlh)||'rkdh'|| ls_rkdh ||'yfbm'||as_yfbm|| '插yfgl_t_ypkctjmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
end;
--
--更新yfgl_t_rkmx的价格as_bz='kc' 库存调价时才调
begin
if as_bz='kc' then
update yfgl_t_rkmx set lsdj=ldec_lsdj where yfbm=as_yfbm and xlh=al_xlh;
end if ;
exception
when others then
os_retmsg := TO_CHAR(al_xlh)||'rkdh'|| ls_rkdh ||'yfbm'||as_yfbm|| '更新yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program; end;
--
oi_return := 1;
os_retmsg := ''; <<end_program>>
null; exception
when others then
oi_return := SQLCODE;
os_retmsg := SQLERRM;
rollback;end yfgl_ypkctj;
写几个与写一个不同吗?
比如下个过程:CREATE OR REPLACE PROCEDURE yfgl_ypkctj(
as_yfbm in varchar2, -- 药房编码、药房部门ID
al_xlh in long, --入库明细系列号
as_tjdh in varchar2 , --新调价单号
adt_now in date , --调价日期
ad_xsj in decimal, --新药库零售价
ad_sl in decimal, --库存数量
as_machine in varchar2 , --机器名
as_yy in varchar2 ,
as_czy in varchar2 , --操作员
as_bz in varchar2 , --标志
os_retmsg out varchar2, --错误信息
oi_return out integer --返回值
-- 返回值:
-- 0 --------
-- 1 --------
-- -1 --------sql语句执行失败,回滚减库存的事务
-- -2 --------非sql错误
) isifzb varchar2(1);
gmp varchar2(1);
lsdj number(16,10);
mrdj number(16,10);
ypdm varchar2(12);
ph varchar2(60);
sccj varchar2(120);
yxq date;
pkg_unit_ratio number(16,10);
dqsl number(16,10);
ykcksl number(16,10);
ykmrdj number(16,10);
yklsdj number(16,10);
rksxh long;
ykrkxlh long;
ly_seq long;
ls_rkdh varchar2(12);
min_pkg_unit varchar2(12);
pkg_unit varchar2(12);
bz varchar2(1);
item_cnname varchar2(100);
item_cnalias varchar2(100);
itempkg_id varchar2(12);
pkg_name varchar2(40);
ykrkdh varchar2(12);
ldec_lsdj number(16,10);
newyklsdj number(16,10);
ldec_rklsdj number(16,10);
begin
--取出入库明细的药品信息
begin
select rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,rklsdj
into ls_rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,ldec_rklsdj
from yfgl_t_rkmx where xlh=al_xlh;
if (pkg_unit_ratio=0 or pkg_unit_ratio is null) then
pkg_unit_ratio:=1;
end if;
if yklsdj is null then
yklsdj :=lsdj * pkg_unit_ratio;
end if;
newyklsdj :=ad_xsj;
--库存调价数量=库存数量,否则=调价数量
dqsl := ad_sl ;
if as_bz ='nt' then
--lsdj :=round(yklsdj/pkg_unit_ratio,10);
ldec_lsdj :=lsdj;
lsdj :=ad_xsj;
yklsdj :=lsdj * pkg_unit_ratio;
newyklsdj :=ldec_lsdj * pkg_unit_ratio;
end if; if as_bz ='wt' then
yklsdj :=lsdj * pkg_unit_ratio;
end if;
if as_bz ='wf' then
lsdj :=ldec_rklsdj;
yklsdj :=lsdj * pkg_unit_ratio;
end if; exception
when others then
os_retmsg := TO_CHAR(al_xlh) || '取yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
end; --if as_bz='kc' or as_bz='wt' then
if as_bz<>'nt' then
ldec_lsdj := 0;
ldec_lsdj := round(ad_xsj/pkg_unit_ratio,10);
end if ; --插调价明细yfgl_t_ypkctjmx
begin
/*
外退反悔:
旧药房零售单价:外退单的零售单价
新药房零售单价;当前库存零售单价
内退反悔:
旧药房零售单价:当前库存零售单价
新药房零售单价:内退单的零售单价
*/
insert into yfgl_t_ypkctjmx (xlh,yfbm,tjdh,ypdm,rkdh,kcsl,mrdj,oldlsdj,newlsdj,oldyklsdj,newyklsdj,tjrq,rkxlh,sccj,czy,pkg_unit_ratio,rksxh,bz,min_pkg_unit,tjyy,item_cnalias,itempkg_id,pkg_name,pkg_unit,item_cnname)
values (yfgl_yfseq.nextval,as_yfbm,as_tjdh,ypdm,ls_rkdh,dqsl,mrdj,lsdj,ldec_lsdj,yklsdj,newyklsdj,adt_now,al_xlh,sccj,as_czy,pkg_unit_ratio,rksxh,as_bz,min_pkg_unit,as_yy,item_cnalias,itempkg_id,pkg_name,pkg_unit,item_cnname);
exception
when others then
os_retmsg := TO_CHAR(al_xlh)||'rkdh'|| ls_rkdh ||'yfbm'||as_yfbm|| '插yfgl_t_ypkctjmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
end;
--
--更新yfgl_t_rkmx的价格as_bz='kc' 库存调价时才调
begin
if as_bz='kc' then
update yfgl_t_rkmx set lsdj=ldec_lsdj where yfbm=as_yfbm and xlh=al_xlh;
end if ;
exception
when others then
os_retmsg := TO_CHAR(al_xlh)||'rkdh'|| ls_rkdh ||'yfbm'||as_yfbm|| '更新yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program; end;
--
oi_return := 1;
os_retmsg := ''; <<end_program>>
null; exception
when others then
oi_return := SQLCODE;
os_retmsg := SQLERRM;
rollback;end yfgl_ypkctj;
是有程序的要求而实现具体功能的。
其次、要明白begin...end;的意义:在PL/SQL中BEGIN..END表示这是一个完整的块,begin ...end;
的意义可以理解为SQL语句执行的上下限,begin 是上限,SQL开始的地方,end是下限sql语句结束的
地方.
最后、明白begin...end;的功能:对包,函数,子程序等的定义至少需要一个begin...end;来开始和结束。
如果程序中为了某些功能的具体需要可以添加子begin...end;块。比如可以在可疑的程序段使用子
begin...end;这样可以保证这块可疑程序中如果有错误,而不至于影响该块外部其他程序的执行。
比如楼主的实例代码中的这段子begin...end;:
begin
--取出入库明细的药品信息
begin
select rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,rklsdj
into ls_rkdh,rksxh,ypdm,item_cnname,mrdj,lsdj,sccj,yxq,ph,ifzb,gmp,min_pkg_unit,pkg_unit_ratio,bz,dqsl,pkg_unit,ykcksl,ykmrdj,yklsdj,ykrkdh,ykrkxlh,ly_seq,item_cnalias,itempkg_id,pkg_name,ldec_rklsdj
from yfgl_t_rkmx where xlh=al_xlh;
…………………………
exception
when others then
os_retmsg := TO_CHAR(al_xlh) || '取yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
end;
如果表yfgl_t_rkmx里面不存在where xlh=al_xlh的数据,那么程序就会执行when others then里面的
os_retmsg := TO_CHAR(al_xlh) || '取yfgl_t_rkmx表失败! ~r~n' || SQLERRM;
oi_return := -1;
goto end_program;
然后跳到end_program,执行null,然后程序结束。但是如果这里没有子begin...end;程序就会跳到程序最后的那个exception when others then 里面的代码
oi_return := SQLCODE;
os_retmsg := SQLERRM;
rollback;
这样很明显的就能看出有子begin...end;和没有,oi_return与os_retmsg的赋值就不同,有子begin...end;就能够很容易的知道程序是在哪里异常的。楼主程序中的select into 就是可疑程序,就是很容易抛出异常的代码。希望楼主能够明白。
赞一个begin...end可以看作是一个程序段落,这样代码可读性更强,而且可以在段里做针对性处理,而不作用与其他的段,或者全局。更便于逻辑的控制。
像批处理一样,一段一段的。