2012-02-15 1 views
2

У меня есть расчет в моей БД, чтобы обновить «field1» для «table1» после триггера обновления.firebird - после запуска или обновления триггера

Проблема, связанная с обновлением этого поля, приведет к срабатыванию триггера после обновления и выполнению длительной процедуры и отображению ошибок.

, пожалуйста, сообщите, как обновить «поле1» после запуска триггера «После обновления» и без повторного запуска триггера «после обновления».

Я знаю, что я не могу использовать NEW с After trigger.

Благодаря

+1

как об использовании ДО триггер UPDATE? –

+0

«Я знаю, что я не могу использовать NEW с After trigger». Зачем? НОВЫЕ и OLD мета переменные доступны как для триггеров, так и после UPDATE. –

+0

@AndreiK. OP, вероятно, означает, что нельзя ** писать ** в переменную контекста NEW, в триггере AFTER. Чтение их, конечно, в порядке ... – ain

ответ

4

Можно использовать собственный механизм блокировки на основе переменных контекста, которые предотвращают повторение вызова триггера AFTER UPDATE.

CREATE TRIGGER au FOR table 
    AFTER UPDATE 
    POSITION 0 
AS 
BEGIN 
    IF RDB$GET_CONTEXT('USER_TRANSACTION', 'MY_LOCK') IS NULL THEN 
    BEGIN 
    RDB$SET_CONTEXT('USER_TRANSACTION', 'MY_LOCK', 1); 

    ... 
    Do your update operations here 
    ... 

    RDB$SET_CONTEXT('USER_TRANSACTION', 'MY_LOCK', NULL); 
    END 

    WHEN ANY DO 
    BEGIN 
    RDB$SET_CONTEXT('USER_TRANSACTION', 'MY_LOCK', NULL); 
    EXCEPTION; 
    END 
END 
+0

thats cool same like используя глобальную переменную .... но вместо того, чтобы использовать исключение, я, вероятно, буду использовать выход ...... спасибо, я скоро проверю решение. – Wel

+0

КОГДА ЛЮБОЙ раздел здесь для страхования, что блокировка истечет, если что-то пойдет не так. ИСКЛЮЧЕНИЕ здесь для исключения RETHROWING, если таковое имеется. –

+0

ic thanks alot ..... – Wel

-1

Решение: Используйте BEFORE UPDATE TRIGGER вместо AFTER UPDATE TRIGGER

CREATE TRIGGER some_trigger BEFORE UPDATE ... etc 
+0

Я не могу из-за природы вычислений ........ спасибо – Wel

0

Очевидный ответ, чтобы переключиться на BEFORE UPDATE триггером, как отметил Дж Купер ... Однако, если есть какая-то причина вам абсолютно необходимо использовать AFTER UPDATE, тогда вы должны установить флаг, который говорит, что поле должно быть пересчитано и проверить его в триггере. Один из способов сделать это было бы установить поле для NULL в BEFORE триггером, а затем проверить на NULL в AFTER триггером, т.е.

CREATE TRIGGER bu_trigger BEFORE UPDATE 
BEGIN 
    -- mark field for recalculation if needed 
    IF(update invalidates the field1 value)THEN 
    NEW.field1 = NULL; 
END 

CREATE TRIGGER au_trigger AFTER UPDATE 
BEGIN 
    -- only update if the field is NULL 
    IF(NEW.field1 IS NULL)THEN 
    UPDATE table1 SET field1 = ...; 
END 

Но используя эту технику, вы, вероятно, придется использовать много IF(OLD.field IS DISTINCT FROM NEW.field)THEN проверок в триггерах, чтобы избежать неопределенные обновления в ваших триггерах.

0

простое решение ...

огонь обновление только если значение NEW.FIELD1 действительно новый, как это:

CREATE TRIGGER au FOR table1 
    AFTER UPDATE 
    POSITION 0 
AS 
DECLARE VARIABLE TMP AS NUMBER(15,5); -- SAME DATATYPE OF FIELD1 
BEGIN 
    -- MAKE YOUR CALCULATION 
    TMP=CALCULATEDVALUE; 
    -- UPDATE THE ROW ONLY IF THE VALUES IS CHANGED 
    IF (TMP<>NEW.FIELD1) UPDATE TABLE1 SET FIELD1=:TMP WHERE KEY=NEW.KEY; -- PAY ATTENTION IF TMP OR NEW.FIELD1 CAN BE NULL. IN THIS CASE USE COALESCE OR A DIFFERENCE COMPARISON 
END 

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

  • Нет связанных вопросов^_^