VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 31|回复: 8

高手救命:怎么根据子表的内容触发主表?

[复制链接]

1

主题

2

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2020-3-2 16:00:02 | 显示全部楼层 |阅读模式
io_works主表
wid isFinish finishDate
1 0 null
2 0 null

io_workdes子表
id wid isok
1 1 0
2 1 0
3 1 1

怎么使用触发器实现以下功能:
当子表的isok变为1时,检查其他子记录(根据wid)的isok是不是全部为1,如果为1,则修改主表的isFinish为1,否则不变。

create or replace trigger TR_IO_WORKDES_UPDATE
after UPDATE on IO_WORKDES
for each row
declare
begin
UPDATE IO_WORKS
SET ISFINISH='1' ,FINISHDATE=TO_CHAR(SYSDATE,'YYYY-MM-DD')
WHERE WID=:OLD.WID;
--AND NOT exists (SELECT ID FROM IO_WORKDES WHERE WID=:OLD.WID AND ISOK='0')

end TR_IO_WORKDES_UPDATE;
我写的这个有变异表问题,谢谢!!
回复

使用道具 举报

0

主题

70

帖子

49

积分

新手上路

Rank: 1

积分
49
发表于 2020-5-13 14:30:02 | 显示全部楼层
检查其他子记录(根据wid)的isok是不是全部为1,如果为1,则修改主表的isFinish为1,否则不变。

需要加上if判断条件一下
回复

使用道具 举报

0

主题

70

帖子

49

积分

新手上路

Rank: 1

积分
49
发表于 2020-5-14 08:30:01 | 显示全部楼层
比如:
if :NEW.isok = 1 then
    UPDATE IO_WORKS
      SET ISFINISH='1' ,FINISHDATE=TO_CHAR(SYSDATE,'YYYY-MM-DD')
      WHERE WID=:OLD.WID;
elsif :NEW.isok = 0 then
        null;
end if;
回复

使用道具 举报

0

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2020-6-5 20:45:01 | 显示全部楼层
当子表的isok变为1时,检查其他子记录(根据wid)的isok是不是全部为1,如果为1
???
就是说当对应的wid相同时,并且isok全部为1才修改主表?
如果是这样的话,我想像不到利用触发器能够解决的办法。除非在修改主表后,利用修改条件去修改主表。
回复

使用道具 举报

1

主题

2

帖子

3

积分

新手上路

Rank: 1

积分
3
 楼主| 发表于 2020-7-8 17:15:01 | 显示全部楼层
Top  
yuanin  


   
当子表的isok变为1时,检查其他子记录(根据wid)的isok是不是全部为1,如果为1
???
就是说当对应的wid相同时,并且isok全部为1才修改主表?
如果是这样的话,我想像不到利用触发器能够解决的办法。除非在修改主表后,利用修改条件去修改主表。

  


理解正确。在程序中修改害怕不彻底,触发器最好。
回复

使用道具 举报

0

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2020-7-23 13:45:02 | 显示全部楼层
程序中修改肯定彻底(除非你编程错误)。触发器应该无法实现。
回复

使用道具 举报

0

主题

1

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2020-7-30 18:15:01 | 显示全部楼层
很容易实现,代码见下面:
create or replace trigger tri_io_works
after update or insert on io_works_son
declare
       cursor c is select wid,sum_isok from
       (select wid,sum(nvl(isok,0))/count(nvl(isok,0)) as sum_isok from io_works_son group by wid)
               where sum_isok =1;
       v_wid   io_works_son.wid%TYPE;
       v_isok  io_works_son.isok%TYPE;

begin
     open c;
     loop
         fetch c into v_wid,v_isok;
         exit when c%notfound;
         update io_works set isfinish =1 where wid = v_wid;
     end loop;
end;
回复

使用道具 举报

0

主题

2

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2020-8-1 19:15:01 | 显示全部楼层
如果对于行级触发器
before/* 或者after*/ UPDATE on IO_WORKDES
for each row

if :new.ISOK <> :old.ISOK then
if :new.ISOK='1' then
  if NOT exists (SELECT ID FROM IO_WORKDES
    WHERE WID=:OLD.WID AND ISOK='0' AND ID<>:old/* 或者new*/.ID ) then
   UPDATE IO_WORKS
   ...

还有保错和变异表问题的话

可以用包变量和语句级触发器:
定义一个包变量类型为索引表,也可以用数组
在行级触发器
if :old.ISOK='1' and :new.ISOK ='0' then
widchgs(v_wid)='0';
elseif :old.ISOK='0' and :new.ISOK ='1' then
if not widchgs.EXISTS(v_wid) then
   widchgs(v_wid)='1';
end if;
end if;

在after语句级触发器
可以循环UPDATE IO_WORKS

i := widchgs.FIRST;
WHILE i IS NOT NULL LOOP
...widchgs(i)
i := widchgs.NEXT(i);
END LOOP;


回复

使用道具 举报

0

主题

2

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2020-8-1 19:45:01 | 显示全部楼层
包变量pkgwid.widchgs

在after语句级触发器 循环:

if pkgwid.widchgs(i) ='1' then
  if NOT exists (SELECT ID FROM IO_WORKDES WHERE WID=i AND ISOK='0' ) then
   UPDATE IO_WORKS
....
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2020|verysource.com ( 京ICP备17048824号-1 )

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