【问题标题】:How to prevent saving to database from trigger or stored procedure?如何防止从触发器或存储过程保存到数据库?
【发布时间】:2013-11-27 17:08:43
【问题描述】:

我有一个触发器和存储过程。在存储过程中,我验证了 IPv4 地址。如果地址有效,则将其保存到 DB。如果不是,我的程序会在数据库中保存空记录。我想在 IP 无效时做到这一点 - 没有什么可以保存的。当 ip 无效时,我不知道如何停止该过程。我知道不应该在数据库级别提供验证,但这是要求。你能帮我修复我的代码吗...?谢谢:)

 DELIMITER $$
CREATE TRIGGER `validation_test_trigger` BEFORE INSERT ON setting_parameters
FOR EACH ROW 
BEGIN 
IF(NEW.parameter_name LIKE 'proxy_test') = true THEN
CALL validate_ip(NEW.parameter_value);
end IF;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS validate_ip;
DELIMITER // 
CREATE PROCEDURE validate_ip(INOUT ip VARCHAR(45)) 
BEGIN 
select INET_NTOA(INET_ATON(ip)) into ip;
IF(ip REGEXP '^([1-9]|[1-9][0-9]|1[013-9][0-9]|12[0-689]|2[0-4][1-9]|25[0-4])\.(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][1-9]|25[0-4])$')=0
THEN
  SIGNAL SQLSTATE '12345'
   SET MESSAGE_TEXT = 'Invalid IP!';
     END IF;
END // 
DELIMITER ; 

【问题讨论】:

    标签: mysql triggers ipv4


    【解决方案1】:
    1. 创建一个函数,而不是一个过程,如果 IP 正确则返回 0,否则返回 1。
    2. 创建一个表b_setting_parameters,类似于setting_parameters,但使用ENGINE=BLACKHOLE。这将创建一个表,该表会丢弃插入其中的所有内容(如 /dev/null)
    3. 在那个黑洞表上创建插入触发器:

      CREATE TRIGGER validation_test_trigger BEFORE INSERT ON b_setting_parameters
      FOR EACH ROW
      BEGIN
        IF validate_ip(NEW.parameter_value) = 0 THEN
          INSERT INTO setting_parameters(col1, col2,...)
          VALUES (NEW.col1, NEW.col2,...)
        END IF;
      END$$
      
    4. 现在您必须在表中插入 b_setting_parameters 而不是 setting_parameters,这样就可以了。

    【讨论】:

      【解决方案2】:

      正如您所说,这不应该在数据库级别完成 - 我不认为 MySQL 触发器允许阻止插入或更新。

      我可以看到成功的唯一方法是让您的触发器更改数据,以便 MySQL 无法插入它......但鉴于 MySQL 经常操纵数据以适应表定义,我不确定这是否会起作用。

      【讨论】:

      • oracle 确实支持可以执行此操作的INSTEAD OF 触发器。对于 mysql,您必须使用黑洞引擎插件来欺骗(见我的回答)
      猜你喜欢
      • 2018-01-18
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-22
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多