一个Oracle触发器的例子

来源:互联网 发布:中信淘宝会员信用卡 编辑:程序博客网 时间:2024/05/22 04:29

有一个表,表名是xx,有ABCD四个字段,正常情况下,ABC、ABD这三个字段都可以唯一确定一条记录,按理应该做成唯一索引,但由于历史原因,该表存在重复数据,但要删掉哪一条需要人工判断,无法用语句批量删除,于是唯一索引加不上。但为了保证以后数据的准确性,需要控制新插进去的记录是唯一的。于是我写了一个触发器,当新插进去的记录与现有记录重复时就报错:

 

CREATE global temporary TABLE g_xx_temp
 (flatdocid     int,
  modeldocid     int,flatdocrev int,modeldocrev int) ON COMMIT DELETE ROWS;


CREATE OR REPLACE TRIGGER trg_xx_row
  before INSERT or update
  ON xx
  FOR EACH ROW
  DECLARE
    -- local variables here
  BEGIN
    insert into g_xx_temp(flatdocid,modeldocid,flatdocrev,modeldocrev)
      values(:NEW.flatdocid,:NEW.modeldocid,:NEW.flatdocrev,:NEW.modeldocrev);
  END;


CREATE OR REPLACE TRIGGER trg_xx
  after INSERT or update
  ON xx
  --FOR EACH ROW
  DECLARE
    -- local variables here
    v_count int;
    v_flatdocid int;
    v_modeldocid int;
    v_flatdocrev int;
    v_modeldocrev int;
    CURSOR c_temp IS SELECT flatdocid,modeldocid,flatdocrev,modeldocrev from g_xx_temp;
  BEGIN

    OPEN c_temp; 
    LOOP 
      FETCH c_temp INTO v_flatdocid,v_modeldocid,v_flatdocrev,v_modeldocrev;
      select count(1) into v_count from xx
        where flatdocid=v_flatdocid and modeldocid=v_modeldocid and flatdocrev=v_flatdocrev;
      if (v_count>=2) then
         RAISE_APPLICATION_ERROR(-20001, '非法数据1:flatdocid='||to_char(v_flatdocid)||',modeldocid='||to_char(v_modeldocid)||',flatdocrev='||to_char(v_flatdocrev));
      end if;
     
      select count(1) into v_count from xx
        where flatdocid=v_flatdocid and modeldocid=v_modeldocid and modeldocrev=v_modeldocrev;
      if (v_count>=2) then
         RAISE_APPLICATION_ERROR(-20001, '非法数据1:flatdocid='||to_char(v_flatdocid)||',modeldocid='||to_char(v_modeldocid)||',modeldocrev='||to_char(v_modeldocrev));
      end if;
     
      EXIT WHEN c_temp%NOTFOUND;
    end loop;
   
    CLOSE  c_temp;
    
  END;