Триггер BEFORE INSERT с вызовом хранимой процедуры (DB2 LUW 9.5)

Я пытаюсь создать триггер BEFORE INSERT, который будет проверять входящее значение поля и заменять его тем же полем в другой строке, если это поле равно нулю. Однако, когда я добавляю оператор CALL в свой триггер, возвращается ошибка "The trigger "ORGSTRUCT.CSTCNTR_IN" is defined with an unsupported triggered SQL statement". Я проверил документацию и увидел, что курсоры не поддерживались в BEFORE (часть причины создания хранимой процедуры в первую очередь), но даже когда я удаляю объявление курсора из хранимой процедуры, вызов по-прежнему генерирует ту же ошибку .

Курок:

CREATE TRIGGER orgstruct.cstcntr_IN
        NO CASCADE
        BEFORE INSERT ON orgstruct.tOrgs
        REFERENCING NEW AS r
        FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
    DECLARE prnt_temp BIGINT;
    DECLARE cstcntr_temp CHAR(11);

    SET prnt_temp = r.prnt;
    SET cstcntr_temp = r.cstcntr;

    CALL orgstruct.trspGetPrntCstCntr(prnt_temp,cstcntr_temp);
    SET r.cstcntr = cstcntr_temp;
END

Хранимая процедура:

CREATE PROCEDURE orgstruct.trspGetPrntCstCntr (
    IN  p_prnt              BIGINT,
    OUT p_cstcntr       CHAR(11)
)
SPECIFIC trGetPrntCstCntr
BEGIN
    IF p_prnt IS NULL THEN
        RETURN;
    END IF;

    BEGIN
        DECLARE c1 CURSOR
            FOR
                SELECT cstcntr
                FROM orgstruct.tOrgs
                WHERE id = p_prnt
            FOR READ ONLY;
        OPEN c1;
        FETCH FROM c1 INTO p_cstcntr;
        CLOSE c1;
    END;
END

Согласно документации, в триггере BEFORE разрешено CALL, поэтому я не понимаю, в чем проблема.


person Matt    schedule 07.03.2011    source источник


Ответы (1)


Триггер before может вызывать хранимую процедуру, но хранимый процесс не может делать ничего, что не разрешено в триггере.

В вашем случае уровень доступа к данным по умолчанию для хранимой процедуры SQL — MODIFIES SQL DATA, что не разрешено в триггере. Вы можете воссоздать свою хранимую процедуру, изменив уровень доступа к данным на READS SQL DATA; это позволит вам создать триггер.

Однако: нет причин вызывать хранимую процедуру для чего-то такого простого; Вы можете сделать это с помощью простого встроенного триггера:

create trigger orgstruct.cstcntr_IN
   no cascade
   before insert on orgstruct.tOrgs
   referencing new as r
   for each row
   mode db2sql
   set r.cstcntr = case 
                     when r.p_prnt is not null 
                       then (select cstcntr from tOrgs where id = r.p_prnt fetch first 1 row only) 
                     else r.cstcntr 
                   end;

Это будет НАМНОГО эффективнее, потому что устраняет как вызов хранимой процедуры, так и обработку курсора внутри хранимой процедуры. Даже если вы хотите использовать хранимую процедуру, вы можете убрать курсор внутри хранимой процедуры и повысить производительность.

К вашему сведению: опубликованная вами логика содержит ошибку и всегда будет устанавливать CSTCNTR в NULL. Триггер, размещенный в этом ответе, этого не делает. :-)

person Ian Bjorhovde    schedule 08.03.2011