oracle触发器学习

以前很少接触触发器。需求是这样的,CMS_PRODUCT_BASE表中POI基本信息按照大类的不同,又将数据存在不同的大类表中,如大类为09的poi存储在CMS_PRODUCT_BASE_09表中。现在需要总表和各个分表中的数据要求保持一致。已经有一个触发器,功能是当像总表中插入一条数据时,自动的将该条信息保存到其对应的分表中。

需要完成两个触发器:

1 当总表中删除一条数据时,相应分表中也要删除该条数据。

2 当总表中修改一条数据时,相应分表中的数据也要修改。

完成的程序是这样的。

修改表内容:

create or replace trigger tri_cms_product_base_upd
  after update on cms_product_base
  for each row
declare
  new_table_name varchar2(50);
  sql_str varchar2(2000);

begin
  new_table_name:='cms_product_base_'||:new.big_type;
        
    sql_str:='update '||new_table_name||' b
       set b.name      = '''||:new.name||''',
           b.address   = '''||:new.address||''',
           b.telephone = '''||:new.telephone||''',
           b.key_type='''||:new.key_type||''',
           b.xy_coord.sdo_gtype='||:new.xy_coord.sdo_gtype||',
           b.xy_coord.sdo_srid='||:new.xy_coord.sdo_srid||',
           b.xy_coord.sdo_point.x='||:new.xy_coord.sdo_point.x||',
           b.xy_coord.sdo_point.y='||:new.xy_coord.sdo_point.y||',
           b.road_num='''||:new.road_num||''',
           b.road='''||:new.road||''',
           b.big_type='''||:new.big_type||''',
           b.contrycode='''||:new.contrycode||''',
           b.key_name='''||:new.key_name||''',
           b.province='''||:new.province||''',
           b.city='''||:new.city||''',
           b.area='''||:new.area||''',
           b.adcode='''||:new.adcode||''',
           b.pre='''||:new.pre||''',
           b.cp='''||:new.cp||''',
           b.name_pinyin='''||:new.name_pinyin||''',
           b.road_pinyin='''||:new.road_pinyin||''' where b.poiid = '''||:new.poiid||'''';
   
   execute immediate sql_str;
   

end tri_cms_product_base_upd;
View Code

删除表中记录:

create or replace trigger tri_cms_product_base_del
  after delete on cms_product_base  
  for each row
declare
   new_table_name varchar2(50);
   sql_str varchar2(2000);
begin
   new_table_name:='cms_product_base_'||:old.big_type;
  sql_str:='delete from '||new_table_name||' where poiid = '''||:old.poiid||'''';
   
   execute immediate sql_str;
  
end tri_cms_product_base_del;
View Code

写这两个trigger中遇到的问题:

1 sdo_geometry的处理,直接在动态sql语句中b.xy_coord='||:new.xy_coord||',会报编译错误,说字符串连接有问题。||连接的参数个数有误。这种要分开每个字段写,就好了。

2 空格的问题,调试的时候把sql语句输出来,空格问题一眼就看出来啦。

3 单引号的问题。单引号用三个,’’’

4 trigger的调试,新建一个调试窗口,在调试程序中写触发的语句,就可以调试了。

 

2 继续上个问题:如果更改的字段是大类字段,那么需要在原表中删除这条记录,在新的大类表中添加这条数据。那么上面的写法就不能解决这个问题。

修改后为:

create or replace trigger tri_cms_product_base_upd
  after update on cms_product_base
  for each row
declare
  new_table_name varchar2(50);
  sql_str varchar2(2000);
  sql_str_del varchar2(2000);
  sql_str_ins varchar2(2000);
  old_table_name varchar2(50);

begin
  old_table_name:='cms_product_base_'||:old.big_type;
  new_table_name:='cms_product_base_'||:new.big_type;
  
           
    sql_str:='update '||new_table_name||' b
       set b.name      = '''||:new.name||''',
           b.address   = '''||:new.address||''',
           b.telephone = '''||:new.telephone||''',
           b.key_type='''||:new.key_type||''',
           b.xy_coord.sdo_gtype='||:new.xy_coord.sdo_gtype||',
           b.xy_coord.sdo_srid='||:new.xy_coord.sdo_srid||',
           b.xy_coord.sdo_point.x='||:new.xy_coord.sdo_point.x||',
           b.xy_coord.sdo_point.y='||:new.xy_coord.sdo_point.y||',
           b.road_num='''||:new.road_num||''',
           b.road='''||:new.road||''',
           b.big_type='''||:new.big_type||''',
           b.contrycode='''||:new.contrycode||''',
           b.key_name='''||:new.key_name||''',
           b.province='''||:new.province||''',
           b.city='''||:new.city||''',
           b.area='''||:new.area||''',
           b.adcode='''||:new.adcode||''',
           b.cp='''||:new.cp||''',
           b.name_pinyin='''||:new.name_pinyin||''',
           b.road_pinyin='''||:new.road_pinyin||''' where b.poiid = '''||:new.poiid||'''';
   
   if(old_table_name=new_table_name) 
   then 
   execute immediate sql_str;
   end if;
   
   if (old_table_name<>new_table_name)
     then
     sql_str_del:='delete from '||old_table_name||' where poiid = '''||:old.poiid||''''; 
     sql_str_ins:='insert into '||new_table_name||'(poiid,xy_coord) values ('''||:new.poiid||''',sdo_geometry(2001, 8307, sdo_point_type(0, 0, null), null, null))';
     execute immediate sql_str_del;
     execute immediate sql_str_ins;
     execute immediate sql_str;
     
     end if;

end tri_cms_product_base_upd;
View Code

如果不对sdo_geometry字段初始化,直接执行下面的插入语句的话,会报”原子null”的错误。故在插入时,初始化sdo_geometry字段。然后再用update语句修改坐标值。

posted on 2014-01-15 13:32  lxlck  阅读(269)  评论(0编辑  收藏  举报