Oracle数据库(十三)——触发器中

DML类型触发器

--创建行级触发器,当在productinfo表中增加数据时将激发该触发器
--step1 创建操作事件记录表
CREATE TABLE LOG_TAB
(
  ID    VARCHAR2(10) NOT NULL,
  OPER_TABLE    VARCHAR2(20),
  OPER_KD       VARCHAR2(10),
  OPER_TABLE_PRK    VARCHAR2(50),
  OPER_DATE     DATE,
  constraint    LOG_TAB_PRK primary key (ID)
)
--step2创建用做LOG_TAB表主键的自增长序列
CREATE SEQUENCE LOG_TAB_ID
MINVALUE    1000000000
MAXVALUE    9999999999
START WITH  1000000000
INCREMENT BY 1
--step3 创建触发器
CREATE TRIGGER PRODUCTINFO_OPER_TGR
    BEFORE  INSERT
    ON  PRODUCTINFO
        FOR EACH ROW --每增加一行就会触发一次
        BEGIN
            IF INSERTING THEN
                INSERT INTO LOG_TAB
                VALUES
                (LOG_TAB_ID.NEXTVAL,
                    'PRODUCTINFO',
                    'INSERT',
                    :NEW.PRODUCTID,
                    SYSDATE);
            DBMS_OUTPUT.PUT_LINE('插入数据主键是 ' || :new.PRODUCTID);
--在事件记录表中增加数据,LOG_TAB_ID.NEXTVAL表示得到序列的下一个值,SYSDATE系统时间
            END IF;
        END
--行级触发器使用:new或:old来访问变更前和变更后的数据
--在触发器中使用多种触发事件
CREATE TRIGGER PRODUCTINFO_OPER_DML_TGR
    AFTER INSERT OR UPDATE OR DELETE
    ON PRODUCTINFO
    FOR EACH ROW
BEGIN
    CASE
        WHEN INSERTING THEN
        INSERT INTO LOG_TAB
        VALUES
            (LOG_TAB_ID.NEXTVAL,
                  'PRODUCTINFO',
                    'INSERT',
                    :NEW.PRODUCTID,
                    SYSDATE);
            DBMS_OUTPUT.PUT_LINE('插入数据主键是 ' || :new.PRODUCTID);
        WHEN UPDATEING THEN
        INSERT INTO LOG_TAB
        VALUES
            (LOG_TAB_ID.NEXTVAL,
                  'PRODUCTINFO',
                    'INSERT',
                    :NEW.PRODUCTID,
                    SYSDATE);
            DBMS_OUTPUT.PUT_LINE('修改数据主键是 ' || :OLD.PRODUCTID);
        WHEN DELETEING THEN
                INSERT INTO LOG_TAB
        VALUES
            (LOG_TAB_ID.NEXTVAL,
                  'PRODUCTINFO',
                    'INSERT',
                    :NEW.PRODUCTID,
                    SYSDATE);
            DBMS_OUTPUT.PUT_LINE('修改数据主键是 ' || :OLD.PRODUCTID);
            END CASE;
        END;
--在触发器中使用if
CREATE TRIGGER PRODUCTINFO_OPER_CHK_TGR
    BEFORE UPDATE OF PRODUCTPRICE ON PRODUCTINFO
    FOR EACH ROW
BEGIN
    IF (TO_CHAR(SYSDATE,'dd') = 25 AND :OLD.PRODUCTPRICE >3000) THEN RAISE_APPLICATION_ERROR(-20000'今天是25号,不允许修改价格高于3000的数据!');
--if的判断条件是系统日期是25号而且修改前的价格大于3000
--RAISE_APPLICATION_ERROR,它把应用程序错误传递到客户端,包含两个参数-20999--20000之间的错误代码和错误提示
    INSERT INTO LOG_TAB
    VALUES
            (LOG_TAB_ID.NEXTVAL,
                  'PRODUCTINFO',
                    'INSERT',
                    :NEW.PRODUCTID,
                    SYSDATE);
            DBMS_OUTPUT.PUT_LINE('修改数据主键是 ' || :NEW.PRODUCTID);

END;
--在触发器中使用when
CREATE TRIGGER PRODUCTINFO_WHEN_OPER_CHK_TGR
    BEFORE INSERT ON PRODUCTINFO
    FOR EACH ROW
    WHEN (NEW.CATEGORY = '0100050001')
BEGIN
    DBMS_OUTPUT.PUT_LINE('原价格: ' || :NEW.PRODUCTPRICE);
    :NEW.PRODUCTPRICE := :NEW.PRODUCTPRICE * 0.9;
    DBMS_OUTPUT.PUT_LINE('打折后价格: ' || :NEW.PRODUCTPRICE);
END;
--如果要修改:NEW引用的数据(类似脚本第7行的操作),那么该触发器应为前触发的方式,因为后触发方式中:NEW数据是不允许被修改的,只能被调用,即使能修改也没有任何意义
--为保证数据的完整性,在某种情况下开发人员会利用触发器实现级联操作功能
--实现级联修改的触发器
--实例为提供级联修改产品类型编码的功能,并把原来的编码存放到CATEGROYINFO_BAK 表中。具体来说就是当表CATEGROYINFO的编码发生变化时,PRODUCTINFO表中CATEGORY字段与之对应的编码同样要变化。

--step1创建备份表
CREATE TABLE CATEGROYINFO_BAK AS SELECT * FROM CATEGROYINFO WHERE 1<>1
--该语句表示复制表结构但不复表数据
--step2 创建触发器
CREATE TRIGGER MUTLI_OPER_CHK_TGR
    AFTER UPDATE OF CATEGROYID ON CATEGROYINFO
    FOR EACH ROW
BEGIN
    UPDATE PRODUCTINFO
    SET CATEGORY = :NEW.CATEGROYID
    WHERE CATEGORY = :OLD.CATEGROYID;
    INSERT INTO CATEGROYINFO_BAK VALUES (:OLD.CATEGROYID, :OLD.CATEGROYNAME);

    DBMS_OUTPUT.PUT_LINE('数据已存入 CATEGROYINFO_BAK表中');
END;

你可能感兴趣的:(Oracle与数据库语言)