Oracle创建触发器详解及例子

触发器详解

1。触发器与触发该触发器的SQL语句同属于一个事务,触发器不允许发出任何事务控制语句,如 commit、rollback、savepoint或者set transaction,它只能随着外部事务的提交、回滚而提交、回滚。(但在oracle8i 以及更高的版本中,你可以创建作为自治事务而执行的触发器,在这种情况下,触发器可以做提交或回滚操作,而与触发该触发器的外部SQL所在的事务无关)
2。与上面相同,在触发器内调用的所有过程、函数也都不能有事务控制语句,除非它们被声明为自治事务( declare pragma autonomous_transaction;)。

1.创建表结构

CREATE TABLE TLK_P_NEWS_MDS(
              ID VARCHAR2(1000 BYTE) NOT NULL,
              NEWSID VARCHAR2(1000 BYTE),
              MANDATESCOPE  VARCHAR2(1000 BYTE),
              MANDATETYPE   VARCHAR2(2 BYTE)
);
Create unique Index NEWS_MDS_Index1 On TLK_P_NEWS_MDS(ID)  ;
Create Index NEWS_MDS_Index2 On TLK_P_NEWS_MDS(NEWSID);
Create Index NEWS_MDS_Index3 On TLK_P_NEWS_MDS(MANDATESCOPE);

2.创建触发器

CREATE OR REPLACE TRIGGER tr_p_news AFTER
  DELETE OR
  INSERT OR
  UPDATE ON tlk_p_news FOR EACH row DECLARE integrity_error EXCEPTION;
  errno  INTEGER;
  errmsg CHAR(200);
  BEGIN
    IF inserting THEN
      proc_mandatescope(:new.id,'News',:new.item_mandatescope);
    elsif updating THEN
      proc_mandatescope(:old.id,'News',:new.item_mandatescope);
    elsif deleting THEN
      proc_mandatescope(:old.id,'News',NULL);
    END IF;
  EXCEPTION
  WHEN integrity_error THEN
    raise_application_error(errno, errmsg);
  END;

3.创建存储过程

create or replace PROCEDURE PROC_MANDATESCOPE(
    DATAID       IN VARCHAR2,
    TABLENAME    IN VARCHAR2,
    MANDATESCOPE IN CLOB )
AS
  AV_SPLIT VARCHAR2(2) := ';';
  V_MANDATESCOPE CLOB;
  V_LENGTH      NUMBER;
  V_START       NUMBER;
  V_INDEX       NUMBER;
  V_STR         VARCHAR2(1000);
  V_MANDATETYPE VARCHAR2(2);
  V_SQL         VARCHAR2(1000);--动态sql
BEGIN
  V_SQL:='DELETE FROM TLK_P_'||TABLENAME||'_mds WHERE '||TABLENAME||'ID ='''||DATAID||'''';
  EXECUTE IMMEDIATE(V_SQL);
  IF MANDATESCOPE  IS NOT NULL THEN
    V_MANDATESCOPE := REPLACE(MANDATESCOPE,',',';');
    V_LENGTH       := LENGTH(V_MANDATESCOPE);
    V_START                           :=1;
    V_INDEX                           :=0;
    V_STR                             :='';
    IF INSTR(V_MANDATESCOPE ,AV_SPLIT) >0 THEN
      WHILE(V_START                   <= V_LENGTH)
      LOOP
        V_INDEX         := INSTR(V_MANDATESCOPE, AV_SPLIT, V_START);
        IF V_INDEX       = 0 THEN
          V_MANDATETYPE := SUBSTR(V_MANDATESCOPE, V_START,1);
          V_STR   :=SUBSTR(V_MANDATESCOPE, V_START);
          V_START := V_LENGTH + 1;
        ELSE
          V_MANDATETYPE := SUBSTR(V_MANDATESCOPE, V_START, 1);
          V_STR   :=SUBSTR(V_MANDATESCOPE, V_START, V_INDEX - V_START);
          V_START := V_INDEX                                + 1;
        END IF;
        V_SQL:='INSERT INTO TLK_P_'||TABLENAME||'_mds (ID,'||TABLENAME||'ID,MANDATESCOPE,MANDATETYPE) VALUES('''||SYS_GUID()||''','''||DATAID||''','''||V_STR||''','''||V_MANDATETYPE||''')';
        EXECUTE IMMEDIATE(V_SQL);
      END LOOP;
    ELSE
      V_MANDATETYPE := SUBSTR(V_MANDATESCOPE, V_START,1);
      V_SQL :='INSERT INTO TLK_P_'||TABLENAME||'_mds (ID,'||TABLENAME||'ID,MANDATESCOPE,MANDATETYPE) VALUES('''||SYS_GUID()||''','''||DATAID||''','''||V_MANDATESCOPE||''','''||V_MANDATETYPE||''')';
      DBMS_OUTPUT.PUT_LINE('INPUT1:'||V_SQL ); --監視SQL語句
      EXECUTE IMMEDIATE(V_SQL);
    END IF;
    --提交
  END IF;
END PROC_MANDATESCOPE;


你可能感兴趣的:(oracle)