触发器实现唯一性约束问题CREATE OR REPLACE TRIGGER tg_temp
BEFORE INSERT OR UPDATE  ON temp
FOR EACH ROW
DECLARE 
   vv_count INTEGER;
   exp_errors EXCEPTION;
BEGIN
    SELECT COUNT(*)
    INTO vv_count 
    FROM temp t
    WHERE t.id =:new.id;
    dbms_output.put_line(vv_count);
    IF vv_count!=0   THEN    
        RAISE exp_errors;
    ELSE
        INSERT INTO temp VALUES(:new.id,:new.name);        
    END IF;
EXCEPTION 
    WHEN exp_errors THEN
       dbms_output.put_line('插入错误!');
    WHEN OTHERS THEN
        dbms_output.put_line('其他错误!');
END tg_temp;
测试语句:INSERT INTO temp VALUES(6,'f');
我测试输入了vv_count
结果:0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
其他错误!
为什么会循环输入的,请问如何修改trigger,才可以实现功能!

解决方案 »

  1.   

    for each row的trigger一般是不能对自己这个表来进行query和dml操作的,除非用自治事务来解决。
      

  2.   

    IF vv_count!=0   THEN    
            RAISE exp_errors;
        ELSE
            INSERT INTO temp VALUES(:new.id,:new.name);        
        END IF;这里也是错的,不需要insert into这个语句, 递归了。
      

  3.   

    IF vv_count!=0  THEN    
            RAISE exp_errors; 
        ELSE 
            INSERT INTO temp VALUES(:new.id,:new.name);        
        END IF; 这里也是错的, 不需要insert into这个语句, 递归了。
    对,那我如果想实现唯一约束行功。能该怎么修改呢?
      

  4.   

    你的唯一性约束,为什么要用触发器实现啊?你用UNIQUE约束不就可以了吗。用触发器的性能低于用约束的性能。
      

  5.   

    不能这么写。建唯一约束
    要不参考下面的表级触发器,若有重复,output错误提示,可以选择回滚
    CREATE OR REPLACE TRIGGER tg_temp
    after INSERT OR UPDATE  ON temp
    --FOR EACH ROW
    DECLARE 
       vv_count integer;  
    BEGIN
        SELECT max(COUNT(*))
        INTO vv_count 
        FROM temp t
        group  by id; 
        dbms_output.put_line(vv_count);
        IF vv_count>1  THEN        
        dbms_output.put_line('插入错误!');   
        END IF;
    END tg_temp;
      

  6.   

    谢谢大家,只是今天看到有这个一个题目,觉得挺有意思,想练习一下触发器
    IF vv_count!=0  THEN    
            RAISE exp_errors; 
        ELSE 
            INSERT INTO temp VALUES(:new.id,:new.name);        
        END IF; 
    这是递归的原因是什么?
      

  7.   

    是不是因为FOR EACH ROW 对表中的判断然后都进行了INSERT!
      

  8.   


    你这里又insert了一把,相当于又触发了这个trigger
      

  9.   

    你这里是before的trigger,所以调用insert into tmp的时候又会触发这个trigger,所以就不停的递归了