mysql - MySQL在插入后触发错误中删除行
问题描述
我在 MySQL 数据库中有三个表bids
,offers
和matched
. 该matched
表包含已匹配的出价和出价。有一个事件运行逻辑来进行如下所示的匹配,该事件有效。
CREATE EVENT bid_offer_matching
ON SCHEDULE EVERY 1 SECOND
STARTS CURRENT_TIMESTAMP
DO
INSERT INTO Matched(
consumer_id, /* Bidder */
producer_id, /* Offer */
bid_id, /* bid id */
offer_id, /* offer id */
volume, /* Volume */
price, /* Price */
market_time) /* Market Time */
SELECT
bids.user_id, /* Bidder */
offers.user_id, /* Offer */
bids.bid_id, /* Bid ID */
offers.offer_id, /* Offer ID */
bids.bid_volume, /* Volume */
bids.bid_price, /* Price */
bids.market_time /* Market Time */
FROM
Bids bids
INNER JOIN (
SELECT *, ROW_NUMBER()
OVER (
PARTITION BY
offer_volume /* Partition by the volume in the offer */
ORDER BY
/* Order each partiton by the price low to high, this makes row 1 in each partition the lowest price offer*/
offer_price
)rn /* Get the row number also back */
FROM Offers
) offers
ON
/* Volume must be equal */
bids.bid_volume = offers.offer_volume AND
/*Price must be at least asking price */
bids.bid_price >= offers.offer_volume AND
/* Market time must be same */
bids.market_time >= offers.market_time
WHERE
/* This is important, it matches only the above condition to the lowest offer price resulting in best price for bidder */
offers.rn = 1;
当我在表上创建触发器以删除从and表中matched
插入的出价和出价时,就会出现问题。我想删除它们,因为一旦它们匹配就不再需要它们。此触发器的逻辑如下所示。bids
offers
/*Crete the trigger*/
DELIMITER $$
CREATE TRIGGER match_insert_trigger
AFTER INSERT
ON Matched FOR EACH ROW
BEGIN
/* DELETE THE BID*/
DELETE FROM
Bids
WHERE
bid_id=NEW.bid_id; /* The bid ID is inserted into the matched table to be used as reference, not a foreign key though */
/* DELETE THE OFFER */
DELETE FROM
Offers
WHERE
offer_id=NEW.offer_id; /* The offer ID is inserted into the matched table to be used as reference, not a foreign key though */
END$$
DELIMITER ;
但是,当尝试执行事件以匹配出价和出价时,现在会发生错误
Error Code: 1442. Can't update table 'Bids' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
我只是Bids
在事件中更新表格,match_insert_trigger
但投标表格不用于触发任何事情,所以有点不确定这里有什么问题?
编辑
通过在事件中放置删除匹配的出价/出价的逻辑,我已经实现了我需要的功能bid_offer_matching
。但是,如果有人知道,我仍然不明白上述错误是如何发生的。
下面是新的事件代码
DELIMITER $$
CREATE EVENT bid_offer_matching
ON SCHEDULE EVERY 1 SECOND
STARTS CURRENT_TIMESTAMP
DO
BEGIN
INSERT INTO Matched(
consumer_id, /* Bidder */
producer_id, /* Offer */
bid_id, /* bid id */
offer_id, /* offer id */
volume, /* Volume */
price, /* Price */
market_time) /* Market Time */
SELECT
bids.user_id, /* Bidder */
offers.user_id, /* Offer */
bids.bid_id, /* Bid ID */
offers.offer_id, /* Offer ID */
bids.bid_volume, /* Volume */
bids.bid_price, /* Price */
bids.market_time /* Market Time */
FROM
Bids bids
INNER JOIN (
SELECT *, ROW_NUMBER()
OVER (
PARTITION BY
offer_volume /* Partition by the volume in the offer */
ORDER BY
/* Order each partiton by the price low to high, this makes row 1 in each partition the lowest price offer*/
offer_price
)rn /* Get the row number also back */
FROM Offers
) offers
ON
/* Volume must be equal */
bids.bid_volume = offers.offer_volume AND
/*Price must be at least asking price */
bids.bid_price >= offers.offer_volume AND
/* Market time must be same */
bids.market_time >= offers.market_time
WHERE
/* This is important, it matches only the above condition to the lowest offer price resulting in best price for bidder */
offers.rn = 1;
/* *****DELETE STATEMENT ***** */
/* DELETE THE OFFERS */
DELETE FROM
Offers
WHERE
offer_id
IN
(SELECT offer_id FROM Matched);
/* DELETE THE BIDS */
DELETE FROM
Bids
WHERE
bid_id
IN
(SELECT bid_id FROM Matched);
END$$
DELIMITER ;
解决方案
事件正文中的代码执行INSERT INTO Matched... SELECT ... FROM Bids...
https://dev.mysql.com/doc/refman/8.0/en/stored-program-restrictions.html说:
存储的函数或触发器不能修改已被调用函数或触发器的语句使用(用于读取或写入)的表。
请注意,它说的是“用于阅读或写作”。这意味着,通过在语句中读取Bids 表INSERT...SELECT
,这与您不能修改触发器中的表的规则相冲突,这些表在调用触发器的语句中被读取。
推荐阅读
- css - 显示过渡(多重过渡)
- c++ - 从 C++ 文件中读取特定行
- php - 通过检索 id PHP foreach 删除 mysql 行
- go - 在 Go 中实现构造函数/init 方法的最佳方法是什么
- postgresql - 尽管设置激进,但 Postgresql 9.3 Autovacuum 仍无法跟上
- python - 在 Python 中获取 @classmethod 的内部状态
- java - 在 Android nougat 7.0 上录制通话
- c# - 尝试使用 UWP 和 C# 关闭时出现错误代码
- r - 给定一对值作为条件的二进制矩阵中的条件概率
- javascript - 未将侦听器添加到创建的 div