计算两列到另一列之间的时间差AFTER \ BEFORE INSERT在表中

时间:2019-06-10 13:55:11

标签: mysql database triggers

我有一个用于管理机场的数据库。我想尝试在表FLIGHT_SCHEDULES中的任何INSERT之后,将ArrivingDate和DepartingDate列(均为DATETIME类型)之间的时间差计算为名为Flight_time(TIME类型)的第三列。

我试图创建一个触发器来执行此操作,但是没有成功。我已经在互联网上阅读了一些有关我的错误的信息,但找不到能解决我的困境的东西。

This is the table:

CREATE TABLE FLIGHT_SCHEDULES(
    id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    Flight INT(10) UNSIGNED NOT NULL,
    Airplane INT(10) UNSIGNED NOT NULL,
    DepartingDate DATETIME NOT NULL,
    ArrivingDate DATETIME NOT NULL,
    Flight_time TIME DEFAULT '00:00:00',
    CONSTRAINT flight_unique UNIQUE (Flight),
    CONSTRAINT fk_scheduled_flight_id FOREIGN KEY (Flight) REFERENCES FLIGHTS(id) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT fk_scheduled_airplane_id FOREIGN KEY (Airplane) REFERENCES AIRPLANES(id) ON UPDATE CASCADE ON DELETE CASCADE
);

This is the trigger I created:

delimiter //
CREATE TRIGGER calculate_flightTime2 BEFORE INSERT ON FLIGHT_SCHEDULES FOR EACH ROW
BEGIN
    UPDATE FLIGHT_SCHEDULES
    SET NEW.Flight_time = TIMEDIFF(new.ArrivingDate, new.DepartingDate);
END //

我可以毫无问题地创建触发器,但是我尝试在表中插入新行时收到以下错误消息:

错误代码:1442。无法更新存储的函数/触发器中的表'flight_schedules',因为调用该存储的函数/触发器的语句已使用该表。 0.000秒

请注意,我也尝试创建AFTER触发器,但结果是相同的。

2 个答案:

答案 0 :(得分:0)

这是mysql的限制,因此您不会陷入无限循环。

尝试类似这样的方法。


CREATE TRIGGER calculate_flightTime2 
  BEFORE INSERT
  ON FLIGHT_SCHEDULES 
  FOR EACH ROW
BEGIN
  IF NEW.Flight_time = '00:00:00' THEN
    SET NEW.Flight_time = TIMEDIFF(new.ArrivingDate, new.DepartingDate);
  END IF;
END

答案 1 :(得分:0)

通常,实现可从其他人计算得出的值不是一个好主意。这承担了不一致的风险。例如,如果您更改到达时间会怎样?

因此,最好删除列Flight_time

ALTER TABLE FLIGHT_SCHEDULES
            DROP Flight_time;

为方便起见,您可以创建一个包含计算值的视图。

CREATE VIEW FLIGHT_SCHEDULES_WITH_FLIGHT_TIME
AS
SELECT *,
       timediff(ArrivingDate, DepartingDate) Flight_time
       FROM FLIGHT_SCHEDULES;

在MySQL 8+中,您可以选择使用generated column。这是一种安全的方法,因为DBMS可以保证这样的一致性。

ALTER TABLE FLIGHT_SCHEDULES
            ADD Flight_time time AS timediff(ArrivingDate, DepartingDate);

但是,如果您坚持使用触发器,则无需UPDATE即可在new伪记录中设置值。只需一个任务就足够了。

...
SET NEW.Flight_time = TIMEDIFF(new.ArrivingDate, new.DepartingDate);
...