• Oracle触发器2DML触发器


      DML触发器是最常见的触发器类型,开发人员用的比较多;而其他类型的触发器主要是用于数据库管理或者审计,DBA用的比较多。

    1、DML触发器简介

    BEFORE 触发器

    这种触发器是在某个操作发生之前触发的,比如before insert就是在插入操作之前触发。

    AFTER 触发器

    这种触发器是在某个操作发生之后触发的,比如after update就是在插入操作之前触发。

    语句级别触发器

    这种触发器是由整个SQL语句触发的。这个SQL语句可能操作数据库表的一条或者多条数据。

    行级别触发器

    这种触发器针对的是SQL语句执行过程中操作的每一行记录。假设books表中有1000行记录。下面的update语句就会修改1000行记录:

    update books set title = upper(title);

    如果我在books表上定义了一个行级别的更新触发器,这个触发器就会被触发1000次。

    伪记录 NEW

    这是一个被叫做NEW的数据结构,看起来和PL/SQL中的记录非常相似。只有在更新操作和插入操作的DML触发器中才能使用这个伪记录;这个记录包含的是被操作的行修改之后的值。

    伪记录 OLD

    这是一个被叫做OLD的数据结构,看起来和PL/SQL中的记录非常相似。只有在更新操作和插入操作的DML触发器中才能使用这个伪记录;这个记录包含的是被操作的行修改之前的值。

    WHEN 子句

    DML触发器用这个子句来确定是否应该执行触发器的代码,我们可以用它来避免不必要的执行。

    有关事务

    DML触发器会参与到触发他们的事务中。

    如果触发器抛出了异常,这部分事务会回滚(rollback)。

    如果触发器本身也执行了DML语句(比如向日志表中插入一行数据),这个DML同时也会成为主体事务的一部分。

    不能在DML触发器里执行commit或者rollback语句。

    2、创建DML触发器

    1 CREATE [OR REPLACE] TRIGGER trigger_name   --指定一个触发器名字, or replace 可选
    2 {BEFORE | AFTER}     --指定触发器时机是在语句执行之前或者之后。
    3 {INSERT | DELETE | UPDATE | UPDATE OF column_list } ON table_name --指定触发器应用的DML类型组合:插入、更新或者删除操作。
    4 [FOR EACH ROW]   --如果指定了for each row 则语句处理的每一行记录都会激活触发器。
    5 [WHEN (...)]            --通过这个可选的when子句,可以避免不必要的执行
    6 [DECLARE ... ]  
    7 BEGIN
    8 ...executable statements...    --执行体
    9 [EXCEPTION ... ]     --可选异常处理部分
    10 END [trigger_name];    

    Examples:

    -- an after statement level trigger

    CREATE OR REPLACE TRIGGER statement_trigger
    AFTER INSERT ON to_table
    BEGIN
      DBMS_OUTPUT.PUT_LINE('After Insert Statement Level');
    END;
    /
    /*-- an after row level trigger */
    CREATE OR REPLACE TRIGGER row_trigger
    AFTER INSERT ON to_table
    FOR EACH ROW
    BEGIN
      DBMS_OUTPUT.PUT_LINE('After Insert Row Level');
    END;
    /

    -- a before statement level trigger
    CREATE OR REPLACE TRIGGER before_statement_trigger
    BEFORE INSERT ON to_table
    BEGIN
      DBMS_OUTPUT.PUT_LINE('Before Insert Statement Level');
    END;
    /

    -- a before row level trigger
    CREATE OR REPLACE TRIGGER before_row_trigger
    BEFORE INSERT ON to_table
    FOR EACH ROW
    BEGIN
      DBMS_OUTPUT.PUT_LINE('Before Insert Row Level');
    END;
    /

    -- after insert statement
    CREATE OR REPLACE TRIGGER after_insert_statement
    AFTER INSERT ON to_table
    BEGIN
      DBMS_OUTPUT.PUT_LINE('After Insert Statement');
    END;
    /

    -- after update statement
    CREATE OR REPLACE TRIGGER after_update_statement
    AFTER UPDATE ON to_table
    BEGIN
      DBMS_OUTPUT.PUT_LINE('After Update Statement');
    END;
    /

    -- after delete statement
    CREATE OR REPLACE TRIGGER after_delete_statement
    AFTER DELETE ON to_table
    BEGIN
      DBMS_OUTPUT.PUT_LINE('After Delete Statement');
    END;
    /

    2.1、使用WHEN子句

    例如使用WHEN子句确保只有把薪水修改成不同的值时触发器代码才会执行:

    CREATE OR REPLACE TRIGGER check_raise
       AFTER UPDATE OF salary
       ON employees
       FOR EACH ROW
       WHEN (   (old.salary != new.salary)
             OR (old.salary IS NULL AND new.salary IS NOT NULL)
             OR (old.salary IS NOT NULL AND new.salary IS NULL))
    BEGIN
       NULL;
    END;
    /

    WHEN子句使用注意事项:

    a.要把整个判断逻辑表达式括起来()

    b.不要在OLD和NEW之前加上”:”

    c.使用WHEN子句时只能使用SQL内置函数;

    2.2、使用NEW和OLD伪记录

    CREATE OR REPLACE TRIGGER bef_ins_ceo_comp
       BEFORE INSERT
       ON ceo_compensation
       FOR EACH ROW
    DECLARE
       PRAGMA AUTONOMOUS_TRANSACTION;
    BEGIN
       INSERT INTO ceo_comp_history
           VALUES (
                      :new.name
                    , :old.compensation
                    , :new.compensation
                    , 'AFTER INSERT'
                    , SYSDATE
                  );

       COMMIT;
    END;
    /

  • 相关阅读:
    php使用redis锁
    php接收json数据
    计算机中的二进制、八进制、十进制、十六进制
    mysql8导入myslq5 报错
    如何用最简单的方式解释依赖注入?依赖注入是如何实现解耦的?(通俗易懂)
    【运维】Linux进阶命令简记--Linux(3)
    springboot项目在docker容器中如何优雅关闭
    springboot项目接入sap与部署到docker遇到的问题实录
    如何解决springboot参数传中文乱码
    maven如何动态统一修改版本号
  • 原文地址:https://www.cnblogs.com/AlbertCQY/p/2998198.html
Copyright © 2020-2023  润新知