[本站首页] [管理页面] [写新日志] [退出]

朝为田舍郎,暮登天子堂,将相本无种,男儿当自强。
首页(178) Hibernate(10) JAVA(19) Web(15) Struts(7) 口水(9) Ides(18) 其它(51) AJAX(6) database(29) 
Blog信息

blog名称:四裤全输的小窝~~
日志总数:178
评论数量:699
留言数量:198
访问次数:1151596
建立时间:2005年10月29日

Blog内搜索



日志更新

谷歌地图定位偏移解决方法
【转】利用Windows内置的命令作端口
WIN2003服务器安全加固方案
[转]sql server 日期比较、日
MediaCoder 一般参数设置
[转]VMware中创建共享磁盘阵列的方
缓解vss共享文件夹的安全隐患问题(转)
Delphi 中调用JavaScript
微软的官方方法:延长Windows Se
cxGrid 过滤 排序后 取选中记录的

最新评论

回复:谷歌地图定位偏移解决方法
回复:谷歌地图定位偏移解决方法
回复:WIN2003服务器安全加固方案
回复:cxGrid 过滤 排序后 取选中
回复:TreeView 父节点 子节点 
回复:[转]Oracle Instead
回复:DWR 官方下载地址
ugg  boots
回复:cxGrid 过滤 排序后 取选中
回复:DWR 官方下载地址

友情链接

biglin's Blog
NoisyRam's Blog
Stone's Blog
Kevin 的小家
『知』治通鉴

留言板




[database][转]Oracle Instead of 触发器的使用
文章收藏,  网上资源,  软件技术,  电脑与网络 四裤全输 发表于 2006/12/21 23:11:32

Oracle Instead of 触发器的使用转自:http://blog.dev-club.esnai.com/bscy/archive/2006/08/29/5860.aspx我平时比较少用触发器,主要是因为程序逻辑不对的时候不容易发现错误,有时数据量大了也可能产生性能上的问题,但这个东西总有用武之地,在很多场合还是会起到巨大的作用。      这两天就遇到一个问题,有两张表的一个字段需要进行同步更新,也就是A表修改时要把对应的B表的记录字段修改,反过来B表修改时也要把A表的修改,保持两边数据的一个同步,这个可以在前台很容易的实现,但开发人员不想修改代码了,就考虑在后台用trigger实现。      功能很简单,但在实现时遇到一个问题,就是A上的DML触发了上面的TRIGGER,然后这个TRIGGER去更新B表,这样就会触发B表上的触发器,而B表上的TRIGGER又会更新A表,这样就迭代触发,没有结束了,也就是会产生变异表(mutating)我不知道ORACLE的触发器是否有属性来限制这种情况的发生,但以前做SQL SERVER时知道有种Instaed of的触发器,他表示当DML启动他后,他将以TRIGGER里的代码来代替这个DML动作,也就是DML不会真正的执行,只会启动INSTEAD TRIGGER,最终执行的是TRIGGER里面的编码。      查看了Docs,看到ORACLE也支持这个类型的触发器,但这个只能建立到视图上,不能基于表建立,我要的功能肯定是可以实现的,在这里我把原表进行了rename,引如了两张视图,名字就是以前的表名,这样对于他们前台应用就做了个透明的切换,然后在两个视图上建立INSTEAD触发器,将任何两个视图上的更新都传播到后面的两个基表,这样不管你更新那个视图,我都可以捕获到数据,以代码在后面更新,也不存在互相触发,因为触发器修改的对象已经转移到表了,而此时表上是没有trigger的,呵呵!!!过程如下 --创建测试表SQL> create table mytest1(row_num number,row_name varchar2(50)); 表被创建 SQL> create table mytest2(row_num number,row_name varchar2(50)); 表被创建 --测试数据SQL> INSERT INTO MYTEST1 VALUES(1,'Fuck!!!'); 1 行 已插入 SQL> INSERT INTO MYTEST2 VALUES(1,'Watch your mouth!!!'); 1 行 已插入 SQL> COMMIT; 提交完成 --先在一个表上创建触发器SQL> CREATE OR REPLACE TRIGGER TRI_TEST1  2  BEFORE UPDATE  3  ON MYTEST1  4  FOR EACH ROW  5  DECLARE  6  lv_new VARCHAR2(20);  7  lv_parent VARCHAR2(20);  8  BEGIN  9      lv_new := :new.row_name; 10      lv_parent := :OLD.row_name; 11      IF lv_new <> lv_parent THEN 12          UPDATE MYTEST2 13          SET ROW_NAME = :NEW.ROW_NAME 14          WHERE ROW_NUM = :NEW.ROW_NUM; 15      END IF; 16      DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent); 17  END; 18  / 触发器被创建 --测试更新SQL> set serveroutput onSQL> UPDATE MYTEST1 SET ROW_NAME = 'DO it!!!';DO it!!! Fuck!!! 1 行 已更新 --更新成功SQL> SELECT * FROM MYTEST2;    ROW_NUM ROW_NAME---------- --------------------------------------------------         1 DO it!!!         --另外张表创建触发器SQL> CREATE OR REPLACE TRIGGER TRI_TEST2                2  BEFORE UPDATE                                      3  ON MYTEST2                                         4  FOR EACH ROW                                       5  DECLARE                                            6  lv_new VARCHAR2(20);                               7  lv_parent VARCHAR2(20);                            8  BEGIN                                              9      lv_new := :new.row_name;                         10      lv_parent := :OLD.row_name;                      11      IF lv_new <> lv_parent THEN                       12          UPDATE MYTEST1                                 13          SET ROW_NAME = :NEW.ROW_NAME                   14          WHERE ROW_NUM = :NEW.ROW_NUM;                  15      END IF;                                          16      DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent);       17  END;                                              18  /    --产生了变异表,更新失败SQL> update mytest1 set row_name = 'mouthkkkkkoo'; update mytest1 set row_name = 'mouthkkkkkoo' ORA-04091: table MYTEST1 is mutating, trigger/function may not see itORA-06512: at "TRI_TEST2", line 8ORA-04088: error during execution of trigger 'TRI_TEST2'ORA-06512: at "TRI_TEST1", line 8ORA-04088: error during execution of trigger 'TRI_TEST1'    --更新失败SQL> update mytest2 set row_name = 'mouthkkkkkoo'; update mytest2 set row_name = 'mouthkkkkkoo' ORA-04091: table MYTEST2 is mutating, trigger/function may not see itORA-06512: at "TRI_TEST1", line 8ORA-04088: error during execution of trigger 'TRI_TEST1'ORA-06512: at "TRI_TEST2", line 8ORA-04088: error during execution of trigger 'TRI_TEST2'  --删除触发器SQL> drop trigger TRI_TEST2; 触发器被删掉 SQL> drop trigger TRI_TEST1; 触发器被删掉 --创建视图SQL> CREATE VIEW V_TEST1 AS SELECT * FROM MYTEST1; 视图被创建 SQL> CREATE VIEW V_TEST2 AS SELECT * FROM MYTEST2; 视图被创建 --基于视图创建Instead触发器SQL> CREATE OR REPLACE TRIGGER TRI_TEST1  2  INSTEAD OF UPDATE  3  ON V_TEST1  4  FOR EACH ROW  5  DECLARE  6  lv_new VARCHAR2(20);  7  lv_parent VARCHAR2(20);  8  BEGIN  9      lv_new := :new.row_name; 10      lv_parent := :OLD.row_name; 11      IF lv_new <> lv_parent THEN 12          UPDATE MYTEST2 13          SET ROW_NAME = :NEW.ROW_NAME 14          WHERE ROW_NUM = :NEW.ROW_NUM; 15          UPDATE MYTEST1 16          SET ROW_NAME = :NEW.ROW_NAME 17          WHERE ROW_NUM = :NEW.ROW_NUM; 18      END IF; 19      DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent); 20  END; 21  / 触发器被创建 SQL> CREATE OR REPLACE TRIGGER TRI_TEST2  2  INSTEAD OF UPDATE  3  ON V_TEST2  4  FOR EACH ROW  5  DECLARE  6  lv_new VARCHAR2(20);  7  lv_parent VARCHAR2(20);  8  BEGIN  9      lv_new := :new.row_name; 10      lv_parent := :OLD.row_name; 11      IF lv_new <> lv_parent THEN 12          UPDATE MYTEST2 13          SET ROW_NAME = :NEW.ROW_NAME 14          WHERE ROW_NUM = :NEW.ROW_NUM; 15          UPDATE MYTEST1 16          SET ROW_NAME = :NEW.ROW_NAME 17          WHERE ROW_NUM = :NEW.ROW_NUM; 18      END IF; 19      DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent); 20  END; 21  / 触发器被创建   --功能已经实现SQL> update v_test1 set row_name = 'I rock with you!!!';                                                                                                      1 行 已更新                                                                                                               SQL> commit;                                                                                                              提交完成                                                                                                                  SQL> select * from v_test2;                                                                                                  ROW_NUM ROW_NAME                                          ---------- --------------------------------------------------         1 I rock with you!!!                                                                                                                                                                                               SQL> update v_test2 set row_name = 'Don''t kick me!!!';                                                                   1 行 已更新                                                                                                               SQL> commit;                                                                                                              提交完成                                                                                                                  SQL> select * from v_test1;                                                                                                  ROW_NUM ROW_NAME                                          ---------- --------------------------------------------------         1 Don't kick me!!!                                                                                               SQL> 


阅读全文(8585) | 回复(1) | 编辑 | 精华

回复:[转]Oracle Instead of 触发器的使用
文章收藏,  网上资源,  软件技术,  电脑与网络 shuijing(游客)发表评论于2010/11/5 13:45:15

OK


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除

» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)
站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.035 second(s), page refreshed 144753362 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号