2016-02-04 2 views
0

У нас есть проблема со следующим триггером. Мы хотели бы вставить строку в таблицу UPDATEPROCESSINFO, когда нет строки с новым INSTANCEID и обновить ее для следующих.Триггер, который вставляет несколько строк вместо одного

Но мы были удивлены, обнаружив, что иногда у нас есть несколько строк с тем же INSTANCEID. Это потому, что это было очень быстро? Как предотвратить это? Наша цель - иметь один ряд за INSTANCEID.

Спасибо за помощь

create or replace TRIGGER TRIG_UPDATE_PROCESS_INFO 
    AFTER INSERT ON PROCESSSTEP 
    FOR EACH ROW 
DECLARE 
    AUDIT_TIME TIMESTAMP(6); 
BEGIN 
    SELECT MAX(LASTUPDATETIME) 
    INTO AUDIT_TIME 
    FROM UPDATEPROCESSINFO 
    WHERE INSTANCEID = :NEW.INSTANCEID; 

    IF AUDIT_TIME IS NULL THEN 
    INSERT INTO UPDATEPROCESSINFO 
     (INSTANCEID, STEPID, STEPSTATUS, STEPITERATION, LASTUPDATETIME) 
    VALUES 
     (:NEW.INSTANCEID, :NEW.STEPID, :NEW.STATUS, :NEW.STEPITERATION, :NEW.AUDITTIMESTAMP); 
    ELSIF :NEW.AUDITTIMESTAMP > AUDIT_TIME THEN 
    UPDATE UPDATEPROCESSINFO 
     SET STEPID = :NEW.STEPID, 
      LASTUPDATETIME = :NEW.AUDITTIMESTAMP, 
      STEPSTATUS = :NEW.STATUS, 
      STEPITERATION = :NEW.STEPITERATION 
     WHERE INSTANCEID = :NEW.INSTANCEID; 
    END IF; 
END; 
+0

Как создается «INSTANCEID» при вставке в таблицу «PROCESSSTEP»? Не используется ли последовательность? – Glenn

+0

INSTANCEID сначала создается для таблицы процессов (PROCESS), а затем используется для этапов процесса (PROCESSSTEP) – kkung

+0

Нулевое значение для ': NEW.AUDITTIMESTAMP' также вызовет проблемы. – Glenn

ответ

1

Это может происходить потому, что у вас есть несколько сеансов, которые вставляя в PROCESSSTEP для того же INSTANCEID. Если два сеанса вставляются в PROCESSSTEP почти одновременно, и ни один из них не внес изменений, ни один из них не будет «видеть» изменения другого, и оба будут думать, что строка не существует в UPDATEPROCESSINFO.

У меня такой дизайн, кажется, проблема. Я предлагаю изменить его на таблицу PROCESS_STEP_HISTORY, и по мере завершения каждого шага процесса строка будет вставлена ​​в PROCESS_STEP_HISTORY для записи информации о завершенном шаге процесса. Тогда, когда что-то нужно, чтобы узнать информацию о «последнем» шаг, который был завершен было бы просто сделать что-то вроде

SELECT a.* 
    FROM (SELECT * 
      FROM PROCESS_STEP_HISTORY h 
      WHERE INSTANCE_ID = whatever 
      ORDER BY LASTUPDATETIME DESC) a 
    WHERE ROWNUM = 1 

Он также имеет преимущество сохранения информации о каждом шаге процесса, который может оказаться полезным ,

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

Удачи.

Смежные вопросы