【发布时间】:2019-11-15 14:50:33
【问题描述】:
自从我升级到 MariaDB 10.4.6 后,我的 BEFORE 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 : missing line in view_articles [art ref:11757]”
查询:
select MAX(price)
FROM view_articles
where view_articles.id_ref = 11757;
不返回 null,所以我不应该触发这个错误。
到目前为止我测试过的内容:
- 触发器中“maxprice”的值实际上是 NULL(因此 if 子句没有问题)。
- 如果我修改触发器以在选择查询中将 11757 代替 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 机器上全新安装相同版本,并从转储中加载 db。
编辑更多信息、测试和解决方法: 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 子句的视图?或者这是一个错误?
我对我的解决方法并不十分满意,因为有一天我可能在“文章”表中有负 ID,而在“文章 2”中可能有正 ID,即使现在不是这样。所以我仍然欢迎更优雅的解决方案。
【问题讨论】:
-
如果我替换“view_articles.id_ref = NEW.id_ref;”通过“view_articles.id_ref NEW.id_ref;”然后我得到一个 maxprice 的值。不是我想要的,但它证明触发器可以从视图中读取,它只是在条件的“相等”部分失败......但为什么对我来说仍然是一个谜( id_ref 的类型为 INT(11) )
-
您检查过触发器中的 NEW.id_ref 值吗?它是提供的还是自动递增的? NVM,它在错误消息中,所以它被提供了。
-
@fifonik 是的,NEW.id_ref 的值在我的自定义错误消息中正确返回,它不是自动递增的。当我将它用于桌子而不是我的视野时,它也可以工作。
-
view_articles 是否使用stock 表?不使用聚合函数 (
SELECT price FROM view_articles WHERE ... LIMIT 1) 是否有效? -
@fifonik 我在描述中添加了详细信息。该视图不使用“库存”表。为 LIMIT 1 更改 MAX ( ) 并不能解决问题。