2015-05-31 3 views
1

У меня есть таблица JOB. Он имеет следующие столбцы: cycle_id, job_id, status.Вставка новой строки с помощью триггера в ту же таблицу

Существует 7 заданий, выполняемых для каждого цикла. Таким образом, cycle_id и job_id образуют композитный первичный ключ.

столбец состояния может иметь следующие значения: WAITING_TO_START, RUNNING. COMPLETED.

Каждая работа - работа cron. И каждая работа несет ответственность за другого человека, поэтому для синхронизации каждого человека я использую JOB таблицы базы данных. Каждое задание прослушивает таблицу JOB и наблюдает за ней, если есть строка с указанием job_id и статуса «WAITING_TO_START». Поэтому, когда я хочу, чтобы всякий раз, когда статус задания изменяется на COMPLETED, следующая строка задания создается с cycle_id так же, как и обновленное задание, job_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 ; 

Но когда я выполнить обновление на работу таблицы, я получаю следующее сообщение об ошибке:

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

ERROR 1442 (HY000): Невозможно обновить table 'job' в хранимой функции/триггере, поскольку он уже используется оператором, который вызывается этой хранимой функцией/триггером.

Так что есть способ добиться синхронизации. Я не хочу, чтобы каждая работа создавала строку с идентификатором следующего задания. Я хочу, чтобы он обрабатывался автоматически. Может ли этот триггер быть написан по-другому или я должен использовать какой-то другой механизм.

ответ

1

Вы не сможете 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

Хотя процедура потребует некоторых изменений в код (то есть вам нужно будет вызвать процедуру вместо того, чтобы напрямую обновлять данные), процедура имеет более очевидную возможность: триггеры, выполняющие вещи автоматически в фоновом режиме, могут быть неинтуитивными.