Oracle数据库(十四)——触发器下

触发器执行顺序

在同一个对象上可以作用多个触发器,因此触发器被激活是有先后顺序的:

  • 首先触发的是前语句级触发器(before statement trigger),该触发器执行一次
  • 如果有行级的触发器则接下来执行前行级触发器(before row trigger)该触发器域SQL修改的记录次数一致
  • 当SQL修改记录完成后会触发行级触发器,这是的行级触发器为后触发(after statement trigger),该类型触发的次数同SQL修改记录的次数一致
  • 执行一次语句级的触发器,此时的语句级的出嘎旗为后与狙击触发器(after statement trigger)

如果相同类型,相同事件触发器作用在同一个对象上,如果在Oracle 11g之前,那么最终被执行的会有一定的随机性,在Oracle 11g中利用FOLLOWS可以控制其顺序

CREATE TRIGGER PRODUCTINFO_OPER_ORD_TGR
    BEFORE INSERT
    ON PRODUCTINFO
    FOR EACH ROW 
    FOLLOWS PRODUCTINFO_OPER_TGR
BEGIN
    DBMS_OUTPUT.PUT_LINE('触发器顺序测试');
END;
符合类型触发器

复合类型触发器是Oracle 11g 的新特性,属于触发器的增强部分。复合类型的触发器相当于在一个触发器中包含了4种不同类型的触发器,分别是语句之前(before statement),行之前(before row),语句之后(after statement).这么做可以很轻松地把变量在各状态之间传递

利用该类型的触发器还可以很方便地解决ORA-04091错误,这里涉及一个变异表的概念,读者可以理解变异表是正在被DML操作修改的表,也是触发器的作用表,而触发器通常不能对变异表进行操作,下面一个示例将利用复合类型的触发器,解决ORA-04091错误

--当productinfo表中的数据提高价格时,触发器判断新旧价格差是否高于价格在2000以下的所有产品价格的平均值的20%,如果高于此值,则提示数据有问题
CREATE OR REPLACE TRIGGER COMPOUND_TGR
    FOR UPDATE ON PRODUCTINFO COMPOUND TRIGGER

V_PRO_AVG NUMBER(102) := 0.0;

    BEFORE STATEMENT IS
    BEGIN
        SELECT AVG(PRODUCTPRICE)
        INTO V_PRO_AVG
        FROM PRODUCTINFO
        WHERE PRODUCTINFO.PRODUCTPRICE < 2000;
    END BEFORE STATEMENT;

    AFRER EACH ROW IS 
    BEGIN 
        IF :NEW.PRODUCTPRICE - :OLD.PRODUCTPRICE > V_PRO_AVG * 0.20 THEN
            RAISE_APPLICATION_ERROR(-20011'数据修改错误!');
        END IF;
        END AFTER EACH ROW;
END;
INSTEAD OF 类型触发器

在该类型的触发器作用下,如果对作用对象执行DML操作,那么该操作会被触发器的内部操作所取代。触发器作用在视图当中,用于解决视图不可更新的问题。至于什么样的视图不可更新

--利用INSTEAD OF触发器的使用
--step1,创建视图
    CREATE VIEW PRODUCTINFO_VIEW AS     --视图
    SELECT DISTINCT PRODUCTNAME,PRODUCTPRICE,QUANTITY,CATEGORY,ORIGIN
    FROM PRODUCTINFO;
--STEP2 创建触发器
    CREATE TRIGGER INSTEAD_OF_TGR
        INSTEAD OF INSERT ON  PRODUCTINFO_VIEW
    DECLARE
        CATEGID VARCHAR2(10);
    BEGIN 
        SELECT CATEGROYID
        INTO    CATEGID
        FROM    CATEGROYINFO
        WHERE   CATEGROYINFO.CATEGROYNAME = :NEW.CATEGORY;
        DBMS_OUTPUT.PUT_LINE('------' || CATEGID);
        INSERT INTO PRODUCTINFO
        VALUES
        ('0240090001',
         :NEW.PRODUCTNAME,
         :NEW.PRODUCTPRICE,
         :NEW.QUANTITY,
         CATEGID,
         '测试',
         :NEW,ORIGIN
            );
END;
DDL类型触发器
--该触发器将提示create创建操作,如果有人执行test表的删除操作,提示错误,也不允许对表使用alter操作和rename操作
CREATE TRIGGER DDL_TGR
    BEFORE CREATE OR ALTER OR DROP OR RENAME ON SCHEMA
BEGIN
    IF SYSEVENT = 'CREATE' THEN
--SYSEVENT 事件属性,当前操作
        DBMS_OUTPUT.PUT_LINE(DICTIONARY_OBJ_NAME || '创建中...');
    ELSEIF SYSEVENT = 'DROP' THEN
        IF DICTIONARY_OBJ_NAME = 'TEST' THEN
--DICTIONARY_OBJ_NAME ,操作的对象名称
            RASIE_APPLICATION_ERROR(-20000,'');
        END IF;
    ELSEIF SYSEVENT = 'ALTER' THEN
        RASIE_APPLICATION_ERROR(-20000,'不允许修改表!');
    ELSEIF SYSEVENT = 'RENAME' THEN
        RASIE_APPLICATION_ERROR(-20000,'不允许修改表名称!');
    END IF;
END;
用户和系统事件触发器

所谓的系统触发器,就是基于Oracle系统事件而建立的触发器,该类型的触发器可以审计数据库的登录,注销以及关闭和启动

--step1 创建用户登录日志表
CREATE TABLE LOG_USER (
    LOGONID VARCHAR2(50),
    LOGONNAME   VARCHAR2(50),
    LOGONTIME   DATE,
    CONSTRAINT LOG_USER_PRK PRIMARY KEY (LOGONID)
);
--STEP2 创建触发器,该触发器是数据库级,记录每个用户的登录时间
CREATE TRIGGER  LOGON_TGR
AFTER
LOGON
ON  DATABASE
BEGIN
    INSERT INTO LOG_USER
    VALUES(LOG_TAB_ID.NEXTVAL,SYS.LOGIN_USER,SYSDATE);
END;
删除触发器
DROP TRIGGER DEV_TGR
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值