我现在想做以下的应用,有A、B两张表,结构一样。在A表上建立了一个触发器,当A表有改到时同步到B表上去。但我现在遇到的情况是,当在A表插入一条记录,其中某个列是空的,这时是可以同步到B表。此时我去只修改A表这条记录中原先为空的列,不修改其他任何列,结果是B表上同样的记录中的空列并没有修改。
A表上的触发我是这样写的:只是更新有问题,所以只有更新部分。
create or replace trigger tri_A after insert or update or delete on A REFERENCING NEW AS NEW OLD AS OLD for each row 
if updating then for p in(select A1,A2,A3 where A1=:old.A1)  loop  
if (p.A1!=:new.A1) or (p.A2!=:new.A2) or (p.A2!=:new.A2) or (p.A3!=:new.A3) 
 then update B set B1=:new.A1,B2=:new.A2,B3=:new.A3 where B1=:old.A1; end if; end loop; end if;
end tri_A;
感觉上是空值不能进行!=比较,所以then的部分没有执行。有朋友通到过这种情况吗?要怎样修改触发器才可以?先谢了。

解决方案 »

  1.   

    空值使用不要使用=、!=
    使用is null、is not null
      

  2.   

    什么是NULL?在我们不知道具体有什么数据的时候,也即未知,可以用NULL,
    我们称它为空,ORACLE中,含有空值的表列长度为零。
    ORACLE允许任何一种数据类型的字段为空,除了以下两种情况:
    1、主键字段(primary key),
    2、定义时已经加了NOT NULL限制条件的字段关于NULL:
    1、等价于没有任何值、是未知数。
    2、NULL与0、空字符串、空格都不同。
    3、对空值做加、减、乘、除等运算操作,结果仍为空。
    4、NULL的处理使用NVL函数。
    5、比较时使用关键字用“is null”和“is not null”。
    6、空值不能被索引,所以查询时有些符合条件的数据可能查不出来,
       count(*)中,用nvl(列名,0)处理后再查。
    7、排序时比其他数据都大(索引默认是降序排列,小→大),
       所以NULL值总是排在最后。
      

  3.   

    --原因 select A1,A2,A3 where A1=:old.A1 中的 A1=:old.A1 空值是不能用=判断的 而要用 is null or is not null 判断
    --修改 用nvl 处理下
      

  4.   

    声明部分加
    when (new.A3 is not null and new.A2 is not null and new.A1 is not null)
      

  5.   

    A1是主键来的,所以不存在NULL的问题
      

  6.   


    哦 那既然是主键来的,就没必要后面加 if 判断了,不管修改哪个字段,只要有修改就更新全部字段更新(p.A1!=:new.A1) or (p.A2!=:new.A2) or (p.A2!=:new.A2) or (p.A3!=:new.A3) 
      

  7.   

    如我将这样的一条记录A(1,'',3,4)更新成(1,2,3,4),这时触发器的判断就会变成
    if (1!=1) or (''!=2) or (3!=3) or (4!=4)  
    then ....但上面的(''!=2)是不正确的,因以前没考虑到空值的问题,一直都是这样写的。这几天遇到了空值问题了,才发现不可以执行then后面的语句
      

  8.   

    nvl这样不行嘛
    nvl(p.A2,0)!=:new.A2
      

  9.   


    nvl(p.A2,0)!=:new.A2 --日期 的类型 这个条件是成立的
    nvl(p.A2,to_date('1900-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'))!=:new.A2   你也可以伪造个日期值嘛