MySQL 觸發器

前言

  • 觸發器是與表有關的數據庫對象,在知足定義條件時觸發,並執行觸發器中定義的語句集合。觸發器的這種特性能夠協助應用在數據庫端確保數據的完整性。

一、建立觸發器

  • 1)觸發器只能建立在永久表(Permanent Table)上,不能對臨時表(Temporary Table)建立觸發器。sql

    # 建立觸發器,單條執行語句
    
    # create trigger
        觸發器名                // 不能與已存在的觸發器重複
        觸發時間                // before、after,表示事件以前或以後觸發
        觸發事件                // insert、update、delete 觸發該觸發器的具體事件
      on 
        觸發器響應表名           // 該觸發器操做的表
      for each row
        觸發操做;
    
    > create trigger
        trigger_student_count_insert
        after 
        insert
      on
        student
      for each row
        update student_count set scount = scount + 1;
    
        Query OK, 0 rows affected (0.09 sec)
    # 建立觸發器,多條執行語句
    
    # delimiter $$             // 定義結束符
      create trigger
        觸發器名                // 不能與已存在的觸發器重複
        觸發時間                // before、after,表示事件以前或以後觸發
        觸發事件                // insert、update、delete 觸發該觸發器的具體事件
      on 
        觸發器響應表名           // 該觸發器操做的表
      for each row
      begin
        觸發操做(多條執行語句);   // 每條語句使用分號結束
      end
      $$                       // 使用自定義結束符
    
    > delimiter $$
    > create trigger
        trigger_student_count_insert
        after 
        insert
      on
        student
      for each row
      begin
        update student_count set scount = scount + 1;
        update student_count set scount = scount + 1000;
      end
      $$
    
        Query OK, 0 rows affected (0.10 sec)
  • 2)對同一個表相同觸發時間的相同觸發事件,只能定義一個觸發器。數據庫

    • 例如,對某個表的不一樣字段的 after 更新觸發器,在使用 Oracle 數據庫的時候,能夠定義成兩個不一樣的 update 觸發器,更新不一樣的字段時觸發單獨的觸發器,可是在 MYSQL 數據庫中,只能定義成一個觸發器,在觸發器中經過判斷更新的字段進行對應的處理。
  • 3)使用別名 old 和 new 來引用觸發器中發生變化的記錄內容,這與其餘的數據庫是類似的。函數

    別名 解釋
    new 在觸發器爲 insert 事件類型時有效,表示當前正在插入的數據,如 new.class
    old 在觸發器爲 delete 事件類型時有效,表示當前正在刪除的數據,如 old.class
    > delimiter $$
      create trigger 
        ins_film
        after 
        insert 
      on 
        film 
      for each row 
      begin
        insert into 
          film_text (film_id, title, description)
          values (new.film_id, new.title, new.description);
      end;
      $$
    • 插入 film 表記錄的時候,會向 film_text 表中也插入相應的記錄。

二、刪除觸發器

  • 一次能夠刪除一個觸發程序,若是沒有指定 schema_name,默認爲當前數據庫。ui

    # 刪除觸發器
    # drop trigger [schema_name.]觸發器名;
    > drop trigger trigger_student_count_insert;
    
        Query OK, 0 rows affected (0.00 sec)
    
    # 刪除觸發器,若是觸發器存在就刪除
    # drop trigger if exists 觸發器名;
    > drop trigger if exists trigger_student_count_insert;

三、查看觸發器

  • 能夠經過執行 show triggers 命令查看全部觸發器的狀態、語法等信息。this

    # 查看全部的觸發器
    > show triggers;
    
        *************************** 1. row ***************************
                     Trigger: trigger_student_count_insert
                       Event: INSERT
                       Table: student
                   Statement: begin
                                update student_count set scount = scount + 1;
                                update student_count set scount = scount + 1000;
                              end
                      Timing: AFTER
                     Created: 2018-06-28 18:42:15.47
                    sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,
                              NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                     Definer: root@localhost
        character_set_client: utf8mb4
        collation_connection: utf8mb4_0900_ai_ci
          Database Collation: gbk_chinese_ci
    
        *************************** 2. row ***************************
        ...
    
        ... row in set (0.01 sec)
  • 能夠經過查詢系統表的 information_schema.triggers 表的方式查詢指定觸發器的指定信息。設計

    > use information_schema;
    
        Reading table information for completion of table and column names
        You can turn off this feature to get a quicker startup with -A
    
        Database changed
    
    > desc triggers;
    
        +----------------------------+----------------------------------+------+-----+----------------------+--------------------------------+
        | Field                      | Type                             | Null | Key | Default              | Extra                          |
        +----------------------------+----------------------------------+------+-----+----------------------+--------------------------------+
        | TRIGGER_CATALOG            | varchar(64)                      | NO   |     | NULL                 |                                |
        | TRIGGER_SCHEMA             | varchar(64)                      | NO   |     | NULL                 |                                |
        | TRIGGER_NAME               | varchar(64)                      | NO   |     | NULL                 |                                |
        | EVENT_MANIPULATION         | enum('INSERT','UPDATE','DELETE') | NO   |     | NULL                 |                                |
        | EVENT_OBJECT_CATALOG       | varchar(64)                      | NO   |     | NULL                 |                                |
        | EVENT_OBJECT_SCHEMA        | varchar(64)                      | NO   |     | NULL                 |                                |
        | EVENT_OBJECT_TABLE         | varchar(64)                      | NO   |     | NULL                 |                                |
        | ACTION_ORDER               | int(10) unsigned                 | NO   |     | NULL                 |                                |
        | ACTION_CONDITION           | binary(0)                        | YES  |     | NULL                 |                                |
        | ACTION_STATEMENT           | longtext                         | NO   |     | NULL                 |                                |
        | ACTION_ORIENTATION         | varchar(3)                       | NO   |     |                      |                                |
        | ACTION_TIMING              | enum('BEFORE','AFTER')           | NO   |     | NULL                 |                                |
        | ACTION_REFERENCE_OLD_TABLE | binary(0)                        | YES  |     | NULL                 |                                |
        | ACTION_REFERENCE_NEW_TABLE | binary(0)                        | YES  |     | NULL                 |                                |
        | ACTION_REFERENCE_OLD_ROW   | varchar(3)                       | NO   |     |                      |                                |
        | ACTION_REFERENCE_NEW_ROW   | varchar(3)                       | NO   |     |                      |                                |
        | CREATED                    | timestamp(2)                     | NO   |     | CURRENT_TIMESTAMP(2) | on update CURRENT_TIMESTAMP(2) |
        | SQL_MODE                   | set('REAL_AS_FLOAT',
                                        'PIPES_AS_CONCAT',
                                        'ANSI_QUOTES',
                                        'IGNORE_SPACE',
                                        'NOT_USED',
                                        'ONLY_FULL_GROUP_BY',
                                        'NO_UNSIGNED_SUBTRACTION',
                                        'NO_DIR_IN_CREATE',
                                        'NOT_USED_9',
                                        'NOT_USED_10',
                                        'NOT_USED_11',
                                        'NOT_USED_12',
                                        'NOT_USED_13',
                                        'NOT_USED_14',
                                        'NOT_USED_15',
                                        'NOT_USED_16',
                                        'NOT_USED_17',
                                        'NOT_USED_18',
                                        'ANSI',
                                        'NO_AUTO_VALUE_ON_ZERO',
                                        'NO_BACKSLASH_ESCAPES',
                                        'STRICT_TRANS_TABLES',
                                        'STRICT_ALL_TABLES',
                                        'NO_ZERO_IN_DATE',
                                        'NO_ZERO_DATE',
                                        'INVALID_DATES',
                                        'ERROR_FOR_DIVISION_BY_ZERO',
                                        'TRADITIONAL',
                                        'NOT_USED_29',
                                        'HIGH_NOT_PRECEDENCE',
                                        'NO_ENGINE_SUBSTITUTION',
                                        'PAD_CHAR_TO_FULL_LENGTH')   | NO   |     | NULL                 |                                |
        | DEFINER                    | varchar(93)                      | NO   |     | NULL                 |                                |
        | CHARACTER_SET_CLIENT       | varchar(64)                      | NO   |     | NULL                 |                                |
        | COLLATION_CONNECTION       | varchar(64)                      | NO   |     | NULL                 |                                |
        | DATABASE_COLLATION         | varchar(64)                      | NO   |     | NULL                 |                                |
        +----------------------------+----------------------------------+------+-----+----------------------+--------------------------------+
        22 rows in set (0.00 sec)
    # 查詢指定觸發器
    > select * from triggers where trigger_name = 'trigger_student_count_insert' \G
    
        *************************** 1. row ***************************
                   TRIGGER_CATALOG: def
                    TRIGGER_SCHEMA: test
                      TRIGGER_NAME: trigger_student_count_insert
                EVENT_MANIPULATION: INSERT
              EVENT_OBJECT_CATALOG: def
               EVENT_OBJECT_SCHEMA: test
                EVENT_OBJECT_TABLE: student
                      ACTION_ORDER: 1
                  ACTION_CONDITION: NULL
                  ACTION_STATEMENT: begin
                                      update student_count set scount = scount + 1;
                                      update student_count set scount = scount + 1000;
                                    end
                ACTION_ORIENTATION: ROW
                     ACTION_TIMING: AFTER
        ACTION_REFERENCE_OLD_TABLE: NULL
        ACTION_REFERENCE_NEW_TABLE: NULL
          ACTION_REFERENCE_OLD_ROW: OLD
          ACTION_REFERENCE_NEW_ROW: NEW
                           CREATED: 2018-06-28 18:42:15.47
                          SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
                           DEFINER: root@localhost
              CHARACTER_SET_CLIENT: utf8mb4
              COLLATION_CONNECTION: utf8mb4_0900_ai_ci
                DATABASE_COLLATION: gbk_chinese_ci
        1 row in set (0.00 sec)

四、使用觸發器

  • 觸發器執行的語句有如下兩個限制。code

    • 觸發程序不能調用將數據返回客戶端的存儲程序,也不能使用採用 call 語句的動態 SQL 語句,可是容許存儲程序經過參數將數據返回觸發程序。也就是存儲過程或者函數經過 out 或者 inout 類型的參數將數據返回觸發器是能夠的,可是不能調用直接返回數據的過程。
    • 不能在觸發器中使用以顯式或隱式方式開始或結束事務的語句,如 start trans-action、commit 或 rollback。
  • 觸發器觸發順序orm

    • MySQL 的觸發器是按照 before 觸發器、行操做、after 觸發器的順序執行的,其中任何一步操做發生錯誤都不會繼續執行剩下的操做。若是是對事務表進行的操做,那麼會整個做爲一個事務被回滾(Rollback),可是若是是對非事務表進行的操做,那麼已經更新的記錄將沒法回滾,這也是設計觸發器的時候須要注意的問題 。對象

    • 對於有重複記錄、須要進行 update 操做的 insert,觸發器觸發的順序是 before insert、before update、after update;
    • 對於沒有重複記錄的 insert,就是簡單地執行 insert 操做,觸發器觸發的順序是 before insert、after insert。
    • 對於那些實際執行 update 操做的記錄,仍然會執行 before insert 觸發器的內容,在設計觸發器的時候必定要考慮這種狀況,避免錯誤地觸發了觸發器。事件

相關文章
相關標籤/搜索