在同一 table 上使用触发器插入新行

Inserting new row using a trigger on same table

我有一个tableJOB。它有以下列:cycle_id, job_id, status.

每个周期执行7个作业。所以cycle_idjob_id形成复合主键。

status 列可以具有以下值:WAITING_TO_START, RUNNING. COMPLETED

每个作业都是一个 cron 作业。每项工作由不同的人负责,所以为了同步每个人,我正在使用数据库 table JOB。每个工作都听 JOB table 并观察它是否有一行 job_id 和状态为 'WAITING_TO_START'。因此,每当作业状态更改为已完成时,我想要的是,下一个作业行是用 cycle_id 创建的,与更新的作业相同,job_id 作为更新作业的 id + 1,状态为 'WAITING_TO_START' .所以我为此创建了一个触发器:

DELIMITER $$

CREATE TRIGGER start_new_job
AFTER UPDATE ON job
FOR EACH ROW
BEGIN
IF NEW.status = 'COMPLETED' AND OLD.job_id <=6 THEN
   INSERT INTO job(cycle_id, job_id, status) VALUES (OLD.cycle_id, OLD.job_id+1, 'WATING_TO_START');
END IF;
END$$
DELIMITER ;

但是当我对 JOB table 执行更新时,出现以下错误:

UPDATE job SET status='COMPLETED' WHERE cycle_id=1 AND job_id=1;

ERROR 1442 (HY000): Can't update table 'job' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

那么有没有办法实现同步呢。我不希望每个作业都创建一个包含下一个作业 ID 的行。我希望它自动处理。这个触发器可以用不同的方式编写还是应该使用其他机制。

您将无法 insert into the same table from a trigger。我会用程序替换您的触发器,然后通过程序引导所有状态更新:

CREATE PROCEDURE UpdateJobStatus(jobId INT, NewStatus NVARCHAR(50))
BEGIN
  UPDATE job
     SET `Status` = NewStatus 
     WHERE job_id = jobId;

  IF NewStatus = 'COMPLETED' AND jobId <=6 THEN
    INSERT INTO job(cycle_id, job_id, status) 
       SELECT cycle_id, job_id+1, 'WATING_TO_START'
       FROM job 
       WHERE job_id = jobId;
  END IF;
END;

Sql Fiddle here

虽然该过程需要对您的代码进行一些修改(即您需要调用该过程而不是直接更新数据),但该过程的好处更加明显 - 触发器可以在后台自动执行操作不直观。