io_works主表
wid isFinish finishDate
1 0 null
2 0 nullio_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;
我写的这个有变异表问题,谢谢!!

解决方案 »

  1.   

    检查其他子记录(根据wid)的isok是不是全部为1,如果为1,则修改主表的isFinish为1,否则不变。需要加上if判断条件一下
      

  2.   

    比如:
    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;
      

  3.   

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

  4.   

    Top  
     qiyousyc(沈阳棋友) ( ) 信誉:100    Blog  2007-1-5 15:14:38  得分: 0  
     
     
       
    当子表的isok变为1时,检查其他子记录(根据wid)的isok是不是全部为1,如果为1
    ???
    就是说当对应的wid相同时,并且isok全部为1才修改主表?
    如果是这样的话,我想像不到利用触发器能够解决的办法。除非在修改主表后,利用修改条件去修改主表。  
     理解正确。在程序中修改害怕不彻底,触发器最好。
      

  5.   

    很容易实现,代码见下面:
    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;
      

  6.   

    如果对于行级触发器
    before/* 或者after*/ UPDATE on IO_WORKDES
    for each rowif :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;
      

  7.   

    包变量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 
    ....