我有一个MySQL触发器,可以根据正在运行的UPDATE查询将小时更新为统计表。
触发器是:
DELIMITER //
CREATE TRIGGER update_stats AFTER UPDATE ON user_hours
FOR EACH ROW
BEGIN
IF NEW.hours_committed = 'completed' THEN
INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES
(OLD.user_id, OLD.opportunity_id, -OLD.completed_hours),
(NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
ON DUPLICATE KEY UPDATE
completed_hours = completed_hours + VALUES(completed_hours);
END IF;
END//
工作查询:
UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET user_hours.completed_hours = agreed_hours,
user_hours.hours_committed = 'completed'
WHERE user_hours.hours_committed = 'accepted'
AND user_hours.completed_hours IS NULL
AND user_calendar.date_start = CURRENT_DATE();
我有另一个类似于上面的查询,它更新了同一个表,但检查的completed_hours不为空。查询如下:
UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET user_hours.hours_committed = 'completed'
WHERE user_hours.hours_committed = 'accepted'
AND user_hours.completed_hours IS NOT NULL
AND user_calendar.date_start = '2012-08-23'
上面会触发更新触发器,但是在统计信息表中,completed_hours显示为上次更新查询的0。
对触发器有更好了解的人能够帮助我吗?
谢谢,
标记
答案 0 :(得分:1)
解决方案是:
DELIMITER //
CREATE TRIGGER update_stats AFTER UPDATE ON user_hours
FOR EACH ROW
BEGIN
IF NEW.hours_committed = 'completed' THEN
IF OLD.completed_hours IS NULL THEN
BEGIN
INSERT INTO hours_statistics (user_id,opportunity_id,completed_hours)
VALUES
(OLD.user_id, OLD.opportunity_id, -OLD.completed_hours),
(NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
ON DUPLICATE KEY UPDATE
completed_hours = completed_hours + VALUES(completed_hours);
END;
ELSE
INSERT INTO hours_statistics (user_id,opportunity_id,completed_hours)
VALUES
(NEW.user_id, NEW.opportunity_id, +NEW.completed_hours)
ON DUPLICATE KEY UPDATE
completed_hours = completed_hours + VALUES(completed_hours);
END IF;
END IF;
END//
答案 1 :(得分:0)
在INSERT中,你正在做两行操作 - 一次减法和一次加法。
当你有副本时,ON DUPLICATE KEY将运行两次 - 一次用于减法,一次用于加法。
在第二个查询中,completed_hours没有更改的值,因此OLD和NEW将是相同的。您将添加该值,然后减去该值,产生0。
也许:)。
如果没有,你在某处遇到NULL问题。
编辑:我不确定我是否清楚。这是一个更明确的尝试:您进行第二次更新:
UPDATE user_hours JOIN user_calendar USING (user_calendar_id, opportunity_id)
SET user_hours.hours_committed = 'completed' ...
假设这样找到一个要更新的user_hours行,如下所示:
user_id = 1
opportunity_id = 2
hours_committed = 'accepted'
completed_hours = 10
然后它会触发触发器,它想要运行两个INSERTS:
INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES (1,2,-10)
INSERT INTO hours_statistics (user_id, opportunity_id, completed_hours) VALUES (1,2,+10)
如果违反了UNIQUE KEY,它将运行ON DUPLICATE KEY部分两次,有效地执行:
UPDATE hour_statistics set completed_hours = completed_hours + -10 WHERE...
UPDATE hour_statistics set completed_hours = completed_hours + 10 WHERE...
我试图提出的观点是,最后两个应该相互抵消。如果原始的hour_statistics.completed_hours为0,则触发器触发后它将为0。
这次有意义吗?