在MySQL中创建通用触发器

在MySQL中创建通用触发器,mysql,postgresql,triggers,Mysql,Postgresql,Triggers,在Postgresql中,可以使用创建触发器。这是创建触发器的简便方法。使用相同的触发器过程,可以创建多个触发器,甚至可以将其应用于多个不同的表。我想知道是否有类似的MySQL。我受到这个博客的启发,它为数据库审计创建了一个通用触发器。我的计划是使用MySQL实现类似的方法。但是,MySQL真的有可能创建这样的通用触发器吗?在做了一些研究之后,我了解到在MySQL中没有直接的方法来创建通用触发器。在MySQL中,即使是像prepare语句、execute语句这样的动态SQL语句,也不允许在触发器

在Postgresql中,可以使用创建触发器。这是创建触发器的简便方法。使用相同的触发器过程,可以创建多个触发器,甚至可以将其应用于多个不同的表。我想知道是否有类似的MySQL。我受到这个博客的启发,它为数据库审计创建了一个通用触发器。我的计划是使用MySQL实现类似的方法。但是,MySQL真的有可能创建这样的通用触发器吗?

在做了一些研究之后,我了解到在MySQL中没有直接的方法来创建通用触发器。在MySQL中,即使是像prepare语句、execute语句这样的动态SQL语句,也不允许在触发器内部使用

我找到了一个动态生成触发器的解决方法。假设我们有一个客户表:

CREATE TABLE customer (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  created_on datetime DEFAULT NULL,
  first_name varchar(100) NOT NULL,
  last_name varchar(100) NOT NULL,
  PRIMARY KEY (id)
) 
修订信息表:

CREATE TABLE REVINFO (
  REV int(11) NOT NULL AUTO_INCREMENT,
  REVTSTMP bigint(20) DEFAULT NULL,
  PRIMARY KEY (REV)
) 
审计表:

CREATE TABLE customer_AUD (
  id bigint(20) NOT NULL,
  REV int(11) NOT NULL,
  REVTYPE tinyint(4) DEFAULT NULL,
  created_on datetime DEFAULT NULL,
  first_name varchar(100) DEFAULT NULL,
  last_name varchar(100) DEFAULT NULL,
  PRIMARY KEY (id, REV),
  KEY FK_REV (REV)
) 
现在,我们将编写一个过程,该过程将采用表名并为表的CREATEAUDIT相关触发器生成SQL

DROP PROCEDURE IF EXISTS `proc_trigger_generator`;

DELIMITER $$

CREATE PROCEDURE `proc_trigger_generator` (IN tableName VARCHAR(255))
BEGIN
    DECLARE triggerSQL TEXT DEFAULT "";
    DECLARE cols TEXT DEFAULT "";
    DECLARE col_values TEXT DEFAULT "";
    DECLARE insert_query TEXT DEFAULT "";
    DECLARE colName TEXT DEFAULT "";
    DECLARE done INT DEFAULT FALSE;

    DECLARE cursorDS CURSOR FOR SELECT column_name FROM information_schema.columns cols 
        WHERE cols.table_name = CONCAT(tableName, '_AUD')
            and (column_name != 'REV' && column_name != 'REVTYPE');
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 

    SET triggerSQL = 'DELIMITER ;; \n\n';
    SET triggerSQL = CONCAT(triggerSQL, 'drop trigger if exists tr_', tableName, '_update_audit;; \n\n');
    SET triggerSQL = CONCAT(triggerSQL, 'create trigger tr_', tableName, '_update_audit \n');
    SET triggerSQL = CONCAT(triggerSQL, 'after update \n');
    SET triggerSQL = CONCAT(triggerSQL, '\t on ', tableName, '\n');
    SET triggerSQL = CONCAT(triggerSQL, 'for each row \n');
    SET triggerSQL = CONCAT(triggerSQL, 'begin  \n');
    SET triggerSQL = CONCAT(triggerSQL, '\t DECLARE tmpInt INT; \n');   
    SET triggerSQL = CONCAT(triggerSQL, '\t SELECT COALESCE(MAX(REV), 0) FROM REVINFO into tmpInt; \n\n');  
    SET triggerSQL = CONCAT(triggerSQL, '\t INSERT INTO REVINFO (REV, REVTSTMP) VALUES (tmpInt+1, CURRENT_TIMESTAMP()); \n\n'); 

    SET insert_query = CONCAT(insert_query, 'INSERT INTO ', CONCAT(tableName, '_AUD'), ' (');
    OPEN cursorDS;  
    ds_loop: LOOP
        FETCH cursorDS INTO colName;
        IF done THEN
            LEAVE ds_loop;
        END IF;     
        SET cols = CONCAT(cols, colName, ', ');
        SET col_values = CONCAT(col_values, 'new.', colName, ', ');
    END LOOP;

    SET insert_query = CONCAT(insert_query, cols, 'REV, REVTYPE) VALUES \n');
    SET insert_query = CONCAT(insert_query, '\t\t(', col_values, 'tmpInt+1, 1', ');');
    CLOSE cursorDS;

    SET triggerSQL = CONCAT(triggerSQL, '\t ',insert_query, ' \n\n');
    SET triggerSQL = CONCAT(triggerSQL, 'end;; \n\n');
    SET triggerSQL = CONCAT(triggerSQL, 'DELIMITER ; \n\n');

    SELECT triggerSQL;

END $$
DELIMITER ;

call proc_trigger_generator('customer');
使用customer表名调用过程会为所需触发器生成SQL:

DELIMITER ;; 

drop trigger if exists tr_customer_update_audit;; 

create trigger tr_customer_update_audit 
after update 
        on customer
for each row 
begin  
     DECLARE tmpInt INT; 
     SELECT COALESCE(MAX(REV), 0) FROM REVINFO into tmpInt; 

     INSERT INTO REVINFO (REV, REVTSTMP) VALUES (tmpInt+1, CURRENT_TIMESTAMP()); 

     INSERT INTO customer_AUD (id, created_on, first_name, last_name, REV, REVTYPE) VALUES 
        (new.id, new.created_on, new.first_name, new.last_name, tmpInt+1, 1); 

end;; 

DELIMITER ; 

上面的触发器应该对customer表执行审核任务。
触发器生成器过程可以应用于任何其他表,因为我们希望应用审计相关任务。

审计的许多方面比触发器更实用。对您的需求的实现进行概述,并具体说明您想要审核表单的内容。