MariaDB升级(从10.1升级到10.4.6)后,触发器停止了预期的运行

时间:2019-07-04 23:37:09

标签: mysql triggers mariadb

自从我升级到MariaDB 10.4.6以来,我在使用INSERT INSERT触发器之前遇到了麻烦。

触发器定义如下(删除无用部分)

 CREATE TRIGGER `trg_bins_stock`
 BEFORE INSERT ON `stock`
 FOR EACH ROW
 BEGIN  

DECLARE maxprice DOUBLE DEFAULT NULL;
DECLARE errormsg VARCHAR(255) DEFAULT '';

select  MAX(price)  into maxprice 
FROM view_articles
where view_articles.id_ref = NEW.id_ref;

IF (maxprice is null) THEN

  SET errormsg = CONCAT("INSERT ERROR : missing line in view_articles [art ref :  ",  NEW.id_ref ,  "]");

  SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = errormsg; 

END IF;

END

当插入表格“ stock”时,即使我不应该也收到我的自定义错误,例如消息“ INSERT ERROR:view_articles [art ref:11757]中缺少行”

查询:

select  MAX(price)  
    FROM view_articles
    where view_articles.id_ref = 11757;

不返回null,所以我不应该触发此错误。

到目前为止我已经测试过:

  • 触发器中“ maxprice”的值实际上为NULL(因此if子句不是问题)。
  • 如果我修改触发器以将11757替换为select查询中的NEW.id_ref,则maxprice不是NULL。
  • 如果我创建与视图“ view_articles”相似的表“ table_articles”,并执行INSERT INTO table_articles SELECT * FROM view_articles,然后修改我的触发器以使用表格代替 视图,maxprice也不为空。

其他信息:

Sql模式设置为'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'。 创建视图,表,触发器以及用于插入表的用户是相同的,并且具有“授予的所有特权”。 已在debian 9上使用mariadb 10.4.6(从升级说明页面的10.1升级)进行了测试,并在Windows计算机上全新安装了相同版本的数据库,并从转储中加载了数据库。

编辑更多信息,测试和解决方法: view_articles的定义(简化)如下:

CREATE VIEW view_articles  AS 
 SELECT articles2.id_ref as id_ref, articles2.pricing as price
  from articles2 
 UNION 
SELECT articles.id_article as id_ref, articles.price as price 
  from articles

如果我直接在触发器中代替视图使用此语句,我仍然会遇到相同的问题,但这是可行的:

IF(new.id_ref <0) THEN 
 select MAX(articles2.pricing) INTO maxprix    
      from articles2  WHERE articles2.id_ref =  new.id_ref ;
ELSE 
 select MAX(articles.price) INTO maxprix 
 from articles WHERE articles.id_article = new.id_ref ;
END IF;

那么,现在是否禁止在触发器中使用带有UNION子句的视图?还是这是一个错误?

我对解决方法并不十分满意,因为总有一天我可能在“ articles”表中具有否定ID,而在“ articles2”表中具有肯定性ID,即使目前情况并非如此。因此,我仍然欢迎更优雅的解决方案。

2 个答案:

答案 0 :(得分:0)

我无法重现该问题:

MariaDB [(none)]> USE `_`;
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

MariaDB [_]> SELECT VERSION();
+----------------+
| VERSION()      |
+----------------+
| 10.4.6-MariaDB |
+----------------+
1 row in set (0.000 sec)

MariaDB [_]> SELECT @@global.sql_mode, @@session.sql_mode\G
*************************** 1. row ***************************
 @@global.sql_mode: STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
@@session.sql_mode: STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
1 row in set (0.000 sec)

MariaDB [_]> DROP VIEW IF EXISTS `view_articles`;
Query OK, 0 rows affected (0.000 sec)

MariaDB [_]> DROP TABLE IF EXISTS `articles`, `stock`;
Query OK, 0 rows affected (0.002 sec)

MariaDB [_]> CREATE TABLE IF NOT EXISTS `stock`(
    ->   `id_ref` INT NOT NULL
    -> );
Query OK, 0 rows affected (0.001 sec)

MariaDB [_]> CREATE TABLE IF NOT EXISTS `articles`(
    ->   `id_article` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ->   `price` NUMERIC(10, 2)
    -> );
Query OK, 0 rows affected (0.001 sec)

MariaDB [_]> CREATE VIEW `view_articles`  AS
    -> SELECT `articles`.`id_article` `id_ref`, `articles`.`price`
    -> FROM `articles`;
Query OK, 0 rows affected (0.000 sec)

MariaDB [_]> DELIMITER //

MariaDB [_]> CREATE TRIGGER `trg_bins_stock` BEFORE INSERT ON `stock`
    -> FOR EACH ROW
    -> BEGIN
    ->   DECLARE `maxprice` NUMERIC(10, 2) DEFAULT NULL;
    ->   DECLARE `errormsg` VARCHAR(255) DEFAULT '';
    -> 
    ->   SELECT MAX(`price`) INTO `maxprice`
    ->   FROM `view_articles`
    ->   WHERE `view_articles`.`id_ref` = NEW.`id_ref`;
    -> 
    ->   IF (`maxprice` IS NULL) THEN
    ->     SET `errormsg` := CONCAT('INSERT ERROR: missing line in view_articles [art ref: ',  NEW.`id_ref` ,  ']');
    ->     SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = `errormsg`; 
    ->   END IF;
    -> END//
Query OK, 0 rows affected (0.000 sec)

MariaDB [_]> DELIMITER ;

MariaDB [_]> INSERT INTO `articles`
    -> VALUES (11757, 2000);
Query OK, 1 row affected (0.000 sec)

MariaDB [_]> SELECT `id_article`, `price`
    -> FROM `articles`;
+------------+---------+
| id_article | price   |
+------------+---------+
|      11757 | 2000.00 |
+------------+---------+
1 row in set (0.000 sec)

MariaDB [_]> INSERT INTO `stock`
    -> VALUES (11757);
Query OK, 1 row affected (0.001 sec)

MariaDB [_]> SELECT `id_ref`
    -> FROM `stock`;
+--------+
| id_ref |
+--------+
|  11757 |
+--------+
1 row in set (0.000 sec)

MariaDB [_]> INSERT INTO `stock`
    -> VALUES (1);
ERROR 1644 (45000): INSERT ERROR: missing line in view_articles [art ref: 1]

答案 1 :(得分:0)

这是一个影响MariaDB 10.2、10.3和10.4版本的错误。必须解决该问题,直到修复错误。 MariaDB错误跟踪链接:https://jira.mariadb.org/browse/MDEV-19975