最初的思路是在or后面直接增加付过款的pk,如下
create or replace trigger CSpcace_ACCBANK
before insert or update on bd_accbank
for each row
declare
-- local variables here
begin
if regexp_like(:new.bankacc,'[[:space:]]') or
regexp_like(:new.combineaccnum,'[[:space:]]') or
regexp_like(:new.unitname,'[[:space:]]') or
:new.pk_accbank in
( select ncv5.bd_accbank.pk_accbank from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc
where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc
and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc
and ncv5.bd_accbank.pk_accbank = ncv5.arap_djfb.skyhzh
and ncv5.arap_djfb.payflag in ('1', '2')
)
then
raise_application_error(-20001,'银行账号'||:new.bankacc||'或联行号'||:new.combineaccnum||'或单位名称'||:new.unitname||'有空格,请修改!');
end if;
end CSpcace_ACCBANK;
可是编译不通过,
到现在也不知道oracle为什么不支持or后面使用子查询。
经过研究,得到三种写法,其中第二种是itpub版主写的,不够个人感觉我写的第三个方法最简洁(*^__^*) 嘻嘻……。
2012.7.5 17:27更新:悲剧啊,我认为最好的第三个方法,反而不能使用,具体看第三种写法
方法一,使用游标,注意写法,不在游标定义里面的select使用子查询,并且和select into的区别是这里不用:new(测试真正没有问题)
create or replace trigger CSpcace_ACCBANK before insert or update on bd_accbank for each row declare -- local variables here pk_bas bd_accbank.pk_accbank%type; cursor basjob(id varchar2) is select pk_accbank from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc,ncv5.bd_accbank where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc and ncv5.bd_accbank.pk_accbank = ncv5.arap_djfb.skyhzh and ncv5.arap_djfb.payflag in ('1', '2') and pk_accbank=id; begin open basjob(:new.pk_accbank); loop fetch basjob into pk_bas; exit when basjob%notfound; end loop; close basjob; if regexp_like(:new.bankacc,'[[:space:]]') or regexp_like(:new.combineaccnum,'[[:space:]]') or regexp_like(:new.unitname,'[[:space:]]') or pk_bas is not null then raise_application_error(-20001,'注意:银行账号'||:new.bankacc||'或联行号'||:new.combineaccnum||'或单位名称'||:new.unitname||'有空格或已付款成功,不能修改!'); end if; end CSpcace_ACCBANK;
方法二,itpub版主的i loop循环写法http://www.itpub.net/thread-1632059-1-1.html
create or replace trigger CSpcace_ACCBANK2 before insert or update on bd_accbank for each row declare -- local variables here begin if regexp_like(:new.bankacc,'[[:space:]]') or regexp_like(:new.combineaccnum,'[[:space:]]') or regexp_like(:new.unitname,'[[:space:]]') then raise_application_error(-20001,'注意:银行账号'||:new.bankacc||'或联行号'||:new.combineaccnum||'或单位名称'||:new.unitname||'有空格或已付款成功,不能修改!'); end if; for i in (select * from (select ncv5.bd_accbank.pk_accbank from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc,ncv5.bd_accbank where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc and ncv5.bd_accbank.pk_accbank = ncv5.arap_djfb.skyhzh and ncv5.arap_djfb.payflag in ('1', '2')) where pk_accbank= :new.pk_accbank and rownum = 1) loop raise_application_error(-20001,'注意:银行账号'||:new.bankacc||'或联行号'||:new.combineaccnum||'或单位名称'||:new.unitname||'有空格或已付款成功,不能修改!'); exit; end loop; end ;
方法三,使用select into写法,这里有需要注意:(有bug)
1,使用:new,
2,from后面不使用creat trigger on的表bd_accbank,
3,select的不能是pk_accbank而是客商pk,否则会有提示发生
create or replace trigger CSpcace_ACCBANK2 before insert or update on bd_accbank for each row declare pk_bas varchar2(20); -- local variables here begin select distinct ncv5.bd_cumandoc.pk_cubasdoc into pk_bas from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc and ncv5.arap_djfb.skyhzh=:new.pk_accbank and ncv5.arap_djfb.payflag in ('1', '2'); if regexp_like(:new.bankacc,'[[:space:]]') or regexp_like(:new.combineaccnum,'[[:space:]]') or regexp_like(:new.unitname,'[[:space:]]') or pk_bas is not null then raise_application_error(-20001,'注意:银行账号'||:new.bankacc||'或联行号'||:new.combineaccnum||'或单位名称'||:new.unitname||'有空格或已付款成功,不能修改!'); end if; end ;
通过客商增行录入新的账号的时候,因为:new不存在,因此会报错:
23:21更新:
区分两个不同的trigger,一个是检测空格的,一个是检测付款成功修改账号和单位名称的:
1,空格:
create or replace trigger CSpcace_ACCBANK before insert or update on bd_accbank for each row declare -- local variables here begin if regexp_like(:new.bankacc,'[[:space:]]') or regexp_like(:new.combineaccnum,'[[:space:]]') or regexp_like(:new.unitname,'[[:space:]]') then raise_application_error(-20001,'注意:银行账号、联行号、单位名称中有空格!'); end if; end ;
2,单位名称(使用游标)
create or replace trigger CHECK_ACCBANK before UPDATE on BD_ACCBANK for each row declare -- local variables here pk_bas bd_accbank.pk_accbank%type; cursor basjob(id varchar2) is select pk_accbank from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc,ncv5.bd_accbank where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc and ncv5.bd_accbank.pk_accbank = ncv5.arap_djfb.skyhzh and ncv5.arap_djfb.payflag in ('1', '2') and pk_accbank=id; begin open basjob(:new.pk_accbank); loop fetch basjob into pk_bas; exit when basjob%notfound; end loop; close basjob; if pk_bas is not null then if :new.bankacc<>:old.bankacc or :new.unitname<>:old.unitname then raise_application_error(-20001,'注意:客商账户已成功付款,不能修改账号和名称!'); end if; end if; end;
2012.7.10更新:new和:old差异率:
create or replace trigger C_ACCBANK_NET before UPDATE on BD_ACCBANK for each row declare -- local variables here pk_bas bd_accbank.pk_accbank%type; cursor basjob(id varchar2) is select pk_accbank from ncv5.bd_cubasdoc,ncv5.arap_djfb,ncv5.bd_cumandoc,ncv5.bd_accbank where ncv5.arap_djfb.ksbm_cl = ncv5.bd_cumandoc.pk_cumandoc and ncv5.bd_cumandoc.pk_cubasdoc = ncv5.bd_cubasdoc.pk_cubasdoc and ncv5.bd_accbank.pk_accbank = ncv5.arap_djfb.skyhzh and ncv5.arap_djfb.payflag in ('1', '2') and pk_accbank=id; begin open basjob(:new.pk_accbank); loop fetch basjob into pk_bas; exit when basjob%notfound; end loop; close basjob; if pk_bas is not null then /* if :new.bankacc<>:old.bankacc or :new.unitname<>:old.unitname*/ if utl_match.edit_distance_similarity(:old.bankacc,:new.bankacc)<'90' or utl_match.edit_distance_similarity(:old.unitname,:new.unitname)<'90' then raise_application_error(-20001,'注意:账户已成功付款,不能修改账号或单位名称!'); end if; end if; end;