2016-03-11 2 views
2

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

Вопрос в том, есть ли способ обновить значение генератора непосредственно в триггере?

Я попробовал следующее:

begin 
    if (new.ID is null) then 
    begin 
    new.ID = GEN_ID(mygenerator, 1); 
    end 
    else if (new.ID > GEN_ID(mygenerator, 0)) then 
    begin 
    GEN_ID(mygenerator, new.ID - GEN(ID_mygenerator)); 
    end 
end 

Я также попытался ALTER SEQUENCE или SET GENERATOR заявления, но ни один не кажется, принято в триггере ...

Любое предложение? ПРИМЕЧАНИЕ: Я использую Firebird 2.5.4

+0

Генератор находится вне контроля транзакции, поэтому прямое значение параметра нецелесообразно, так как это может привести к сбросу генератора к уже выданному значению. Я бы ожидал, что триггер, как показано в вашем вопросе, будет работать (хотя, возможно, вам нужно присвоить результат «GEN_ID» локальной переменной). –

ответ

1

Я тестировал это с помощью Firebird 2.5.5 и триггера, созданного Flamerobin (с некоторыми незначительными изменениями), который работает. Важное различие, как представляется, использование присвоения локальной переменной:

CREATE TRIGGER WITH_GENERATOR_BI FOR WITH_GENERATOR ACTIVE 
BEFORE INSERT POSITION 0 
AS 
DECLARE VARIABLE tmp BIGINT; 
BEGIN 
    IF (NEW.ID IS NULL) THEN 
    NEW.ID = GEN_ID(GEN_WITH_GENERATOR_ID, 1); 
    ELSE 
    BEGIN 
    tmp = GEN_ID(GEN_WITH_GENERATOR_ID, 0); 
    if (tmp < new.ID) then 
     tmp = GEN_ID(GEN_WITH_GENERATOR_ID, new.ID - tmp); 
    END 
END 

можно было бы изменить существующий код для назначения временной переменной (и, используя правильный синтаксис для GEN_ID). Однако рекомендуется использовать этот код, так как ваш исходный код (с исправлениями) будет иметь условие гонки, которое может привести к обратному генератору, если параллельно другое действие изменит значение генератора, чтобы оно стало больше, чем NEW.ID. Это условие гонки исключается в первом коде путем присвоения значения GEN_ID(GEN_WITH_GENERATOR_ID, 0) переменной tmp перед проверкой и модификацией.

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