设为首页 收藏本站
查看: 584|回复: 0

[经验分享] oracle 触发器实现多表级联修改

[复制链接]

尚未签到

发表于 2016-7-31 09:46:01 | 显示全部楼层 |阅读模式
应用场景:
table name A
field name:
             yesterday date(昨日日期)
             today date(今日日期)
             yesterdaynum number(昨日数量=totle)
             todaynum number(今日数量)
             totle number(今日总量=yesterdaynum+todaynum)
可见表A昨日数据需要与今日数据相关联,若用户修改了三天前的一个totle字段值,理论上来说应该在这三天发生的数据都要做相应修改。
实现方案:
在table A上做 TRIGGER,每当有update操作时,执行存储过程修改后面相关数据。

CREATE OR REPLACE TRIGGER tr_hyzcupdate
after UPDATE ON A  
FOR  EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
SNWZ.TAL_TEST.p_testEmptyCursor(:old.today,:new.totle);
end tr_hyzcupdate;



create or replace package TAL_TEST is
TYPE myCursorType IS REF CURSOR;
PROCEDURE p_testEmptyCursor(updatedate in date,totle in number);
end TAL_TEST;



create or replace package body TAL_TEST is
PROCEDURE p_testEmptyCursor(updatedate in date,totle in number)
is
pragma autonomous_transaction;
maxdate date;
testdate date;
rowRecord A%ROWTYPE;
myCursorFirst myCursorType ;
execSql varchar2(2000);
updateRowRecord A%ROWTYPE;
updateMyCursorFirst myCursorType ;
--disableTrigger varchar2(2000);
--enableTrigger varchar2(2000);
begin
--查询出表中最后一条记录
select max(today) into maxdate from A;
testdate:=updatedate;
--disableTrigger:='alter trigger  tr_hyzcupdate disable';
--enableTrigger:='alter trigger  tr_hyzcupdate enable';
-- execute immediate disableTrigger;
--循环需要修改的记录
while testdate !=maxdate+1 loop
OPEN myCursorFirst FOR
select *  from A t where t.today=testdate;
FETCH myCursorFirst INTO rowRecord;
IF myCursorFirst%notfound THEN
exit;
ELSE
OPEN updateMyCursorFirst FOR
select *  from A t where t.today=(testdate+1);
dbms_output.put_line( testdate+1);
FETCH updateMyCursorFirst INTO updateRowRecord;
IF updateMyCursorFirst%found THEN
-- else
if testdate=updatedate then
dbms_output.put_line('the first update');
execSql:= 'update A t set t.yesterdaynum='||totle||',t.totle='||(totle+updateRowRecord.todaynum) ||' where to_char(t.today,''YYYY-mm-dd'')='''||to_char(updateRowRecord.Today,'YYYY-MM-dd''')||'';
else
execSql:= 'update A t set t.yesterdaynum='||rowRecord.totle||',t.totle='||(rowRecord.totle+updateRowRecord.todaynum) ||' where to_char(t.today,''YYYY-mm-dd'')='''||to_char(updateRowRecord.Today,'YYYY-MM-dd''')||'';
end if;
dbms_output.put_line(execSql);
execute immediate execSql;
commit;
END IF;
end if;
testdate:=testdate+1;
end loop;
--  execute immediate enableTrigger;
end;
end TAL_TEST;


在此遇到几个问题有的解决有的没解决:
问题一:关于变异表问题,因为涉及到修改时候触发动作,而后又操作本表,所以会出现deadlock问题,解决方法--通过设置oracle自治事务
问题二:例如today是2015-03-13 其实上面的代码做了两次update a where today=2015-03-13,为什么这样做呢?因为触发update时候,在执行存储过程期间,被触发的那条记录是没有提交的,所以我们修改后面的记录虽然有commit ,但是数据是不会发生变化的,解决方法,在存储过程中单独执行update a where today=2015-03-13;
问题三:因为触发器是update,而存储过程也是循环每条数据执行update,所以每次update都会调用触发器,所以如果修改n条记录,其实会触发n次触发器,就是这个问题不知如何解决,试过的方案有:在执行存储过程期间将trigger set disable,不成功。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-251472-1-1.html 上篇帖子: ORACLE管道化表函数实例 下篇帖子: Oracle表分区详解(优缺点)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表