不好办,因为在表A的触发器中是无法再查询表A的,也就是无法得到上一次或前一天的a,b,c的值,最好在程序中处理。

解决方案 »

  1.   

    to developer2002(开发者2002):
       实际上,我的开发中没有并行的操作,所以不用考虑
    to Lastdrop(空杯):
       第一个问题,我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值,则将插入值加上原有值作为这个字段的插入值,否则不变,判断完成后,
    用新的inserted表中插入值更新这行数据,同时
    select *
    from inserted into 表A
      我对oracle不熟,不知道是否有类似的触发以及inserted表?
      

  2.   

    如果有表C,第一个问题可以解决,不过oracle的语法和SQL SERVER是有差别的。create or replace trigger test 
    before insert on A
    for each row
    declare
      last_a number;
      last_b number;
      last_c number;
    begin
      SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a,
       last_b, last_c FROM c;
      if :new.a < last_a then
         :new.a := :new.a + last_a;
      end if;
      if :new.b < last_b then
         :new.b := :new.b + last_b;
      end if;
      if :new.c < last_c then
         :new.c := :new.c + last_c;
      end if;
      
      update c set a=:new.a, b=:new.b, c=:new.c;
    end;
    /如果你用同样类似的方法,创建一个表D保存最近一次0点的记录,那么也可以在触发器中实现。
      

  3.   

    to  Lastdrop(空杯):
       这些语句在哪里执行(sql server里有查询分析器),我用的oracle的可视界面创建,逐行触发,旧值与新值该怎么添?
       oracle易用性好像不太好,错误提示尽是些问号,你能不能帮我在你那里调试一下,看能不能正常触发
    你上面的语句末尾再添加:
       INSERT INTO A
       SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0)
       FROM C
    THANKS!
      

  4.   

    1. 一般是通过SQL*Plus执行,有可视界面的也有命令行方式的。首先创建触发器,就是把我的那些语句执行一下,触发器中的新值与旧值不用你来填,当执行插入操作是,要插入的就是新值,通过:new.field_name访问,而当进行update操作时,原来的记录就是旧值,而要更新的值为新值,在进行删除时,只有旧值。2.错误提示尽是些问号是字符集问题,显示的是中文错误提示会出现这种问题。3. 我不知道为什么要加上
      INSERT INTO A
       SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0)
       FROM C
    这个语句,应该是这个语句会触发我上面写的那个触发器。
      

  5.   

    to tuidler():
    请看看楼主的话
    “我现在有一个sql server下的解决方法,添加一个表C,各字段和A一样,对每个字段作instead of insert 触发,表C始终是一行数据,在插入时对每一个字段的插入值与表C的这行数据进行比较如果插入值小于原有值” SELECT NVL(MAX(a),0),NVL(MAX(b),0),NVL(MAX(c),0) INTO last_a,
       last_b, last_c FROM c;
     请注意记录是从表C,而非表A中取得,表C中存放的就是最近一次的记录,之所以用MAX是防止表C中没有记录是执行SELECT INTO语句出错。
      

  6.   

    哦,是吗,还是自己没看清楚了,如果这样,解决就比较好办了。
    其实不加这个表也好解决,就是取记录MAX(ROWID)
      

  7.   

    Lastdrop(空杯)作法也没错啊,C中始终只有一条记录,就是插入前的上一条记录,不过应该不用取最大值也可以吧!
    to Lastdrop(空杯):哦,原来我是想用C表起一个过滤的作用,我是直接插入到c表,在C表上判断后再插入A表,和你说的是一个道理,主要是考虑第二个问题还要在A表上建立一个插入的触发器,是不是分开会好一点?
      

  8.   

    1.在表A的触发器中是不能执行对表A的查询的
    2.MAX(ROWID)并不一定就是最近的一条记录,当记录不是连续存放时,ROWID也不连续。
      

  9.   

    to tuidler() :
    能说说用MAX(ROWID)具体的实现方法吗?谢谢!
      

  10.   

    to realdreaming()
    1. 当你第一次插入A表时,(当然你现在A表和C表中都有记录)此时C表中没有记录,若此时调用select a,b,c into last_a,last_b,last_c from c,就会报错,所以我们的习惯对SELECT INTO语句即使知道可以取到值,也使用min或MAX之类的函数以保证安全。2.第二个问题,你可以为C表建立触发器,判断插入记录为当天0点时,从A表取出前一天的值进行计算后插入到B表中。这样就不需要建立D表作为中间表了。
      

  11.   

    to Lastdrop(空杯):
    1."在表A的触发器中是不能执行对表A的查询的"这句话确实很关键(在sql server里是可以的)
    2.触发器的时间比较以及插入B表时的格式转换该怎么处理(我对oracle的时间函数不了解)
    谢谢!
      

  12.   

    Oracle提供日期转换函数将数据库中的DATE类型的时间显示为所需格式或进行比较时使用
    to_char(date_field,date_format)
      date_format有很多,比如'yyyy-mm-dd'等将字符串表示的时间转换成数据库中DATE类型的值
    to_date('2003-02-14 00:00:00','yyyy-mm-dd hh24:mi:ss')
      

  13.   

    to Lastdrop(空杯):第二个问题,我试着为C表建立after update 触发器
    但是建不来,受"在表A的触发器中是不能执行对表A的查询的"制约!
      

  14.   

    你是不是在对表C进行UPDATE时,在TRIGGER中对表A进行了操作,而且为表A建立了
    触发器?按照上面的讨论应该不需要为表A创建触发器,请先将表A的触发器drop掉。drop trigger trigger_name;
      

  15.   

    你上面的意思不是通过为A建立触发器解决第一个问题,然后为C建立触发器解决第二个问题吗?
    我觉得你说的对阿!
    能不能告诉我针对C的触发器语句写法,我实在是对oracle语法不熟阿!
    谢谢!
      

  16.   

    “原来我是想用C表起一个过滤的作用,我是直接插入到c表,在C表上判断后再插入A表,和你说的是一个道理,主要是考虑第二个问题还要在A表上建立一个插入的触发器,是不是分开会好一点?”我觉得因为你总是需要以前的一些信息,所以最好不要为表A建立触发器,就按你说每次都是先对C表进行update,在其update触发器中完成对A表和B表的操作。create or replace trigger test
    after update on C
    for each row
    begin
      if :new.a < :old.a then
         :new.a := :new.a + :old.a;
      end if;
      if :new.b < :old.b then
         :new.b := :new.b + :old.b;
      end if;
      if :new.c < :old.c then
         :new.c := :new.c + :old.c;
      end if;
      
      insert into A (time, a, b, c) 
       values(sysdate, :new.a, :new.b, :new.c);
      -- B
      if to_char(sysdate,'hh24:mi:ss') = '00:00:00' then
         -- 不好意思,我还没有找到得到前一天的函数,所以只能....
        insert into B ....
      end if;
    end;
    /
      

  17.   

    不好意思,这个trigger应该是before update而不是after update
      

  18.   


    B表中存放的是两个相邻0点的差值,所以还得从A表中找到最近的0点值再相减后插入B表
    语句该怎么写呢?这样可以吗?
    IF to_char(time,'hh24:mi:ss') = '00:00:00' then
    SELECT top 1
    INTO last_a,last_b, last_c 
    FROM a
    WHERE to_char(time,'hh24:mi:ss') = '00:00:00' 
    ORDER BY time desc
    last_a :=:new.a -last_a 
    last_b :=:new.b -last_b   
    last_c :=:new.c -last_c
    INSERT INTO B(TIME,last_a,last_b, last_c )  --这里的TIME怎么能取道上一个0点的值,还得是YYYY-MM-DD格式!