Триггер для проверки значений для вставки - PullRequest
0 голосов
/ 12 октября 2018

У меня есть две таблицы, которые здесь задействованы из двух разных схем.

Службы схемы и задача таблицы - идентификатор столбца

Schme mona_internal и таблица officius_unos - задача столбца

Мне нужен триггер при вставке в таблицу задач столбца officius_unos, чтобы проверить, существует ли значение вставки в идентификатор столбца из задачи таблицы.Если существует, чтобы продолжить вставку, она не существует, чтобы вызвать ошибку.

Вот триггер:

CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA 
    BEFORE INSERT ON OFFICIUS_UNOS 
    FOR EACH ROW 
    DECLARE
        task_provera number(10);

        BEGIN
            select id into task_provera from servis.task
            where id=:new.task;

            if (task_provera is null)
                then raise_application_error(-20101, 'No task');
                else insert into mona_internal.OFFICIUS_UNOS (task) values (:new.task);
            end if;    

        END;

Триггер скомпилирован, но проблема возникает при попытке вставитьНовое значение в таблице задач столбца officius_unos возвращает мне это сообщение

insert into officius_unos (task) values (291504);

    Error report -
    ORA-00036: maximum number of recursive SQL levels (50) exceeded
    ORA-00036: maximum number of recursive SQL levels (50) exceeded
    ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 5
    ORA-04088: error during execution of trigger 'MONA_INTERNAL.PROBA_PROBA'
    ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 10

И значение 291504 существует в табличной задаче в столбце с идентификатором.

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

Oracle: использование подзапроса в триггере

1 Ответ

0 голосов
/ 12 октября 2018

Вам не нужно вставлять в триггер вставки.

Если триггер успешен, Oracle продолжит работу с INSERT самостоятельно.

Поэтому немедленное решение - удалить INSERT из триггера:

CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA 
    BEFORE INSERT ON OFFICIUS_UNOS 
    FOR EACH ROW 
DECLARE
    task_provera number(10);
BEGIN
    select id 
       into task_provera 
    from servis.task
    where id=:new.task;

    if (task_provera is null) then 
      raise_application_error(-20101, 'No task');
    end if;
    // nothing do do here
END;

Однаковыше все еще не правильно.Если id не существует в servis.tak, SELECT выдаст исключение NO_DATA_FOUND.

Одним из решений этой проблемы является использование агрегатной функции, которая всегда будет возвращать одну строку.Если ни одна строка не соответствует критерию WHERE, возвращается значение NULL:

CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA 
    BEFORE INSERT ON OFFICIUS_UNOS 
    FOR EACH ROW 
DECLARE
    task_provera number(10);
BEGIN
    select max(id) 
       into task_provera 
    from servis.task
    where id=:new.task;

    if (task_provera is null) then 
      raise_application_error(-20101, 'No task');
    end if;
    // nothing do do here
END;

Или вы можете явно перехватить исключение:

CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA 
    BEFORE INSERT ON OFFICIUS_UNOS 
    FOR EACH ROW 
DECLARE
    task_provera number(10);
BEGIN
    select max(id) 
       into task_provera 
    from servis.task
    where id=:new.task;

    if (task_provera is null) then 
      raise_application_error(-20101, 'No task');
    end if;

EXCEPTION 
   WHEN NOT_DATA_FOUND THEN 
      raise_application_error(-20101, 'No task');
END;

Но правильный подход - использоватьограничение внешнего ключа для чего-то подобного.

alter table mona_internal.PROBA_PROBA 
   add constraint fk_proba_task
   foreign key (task)
   references servis.task (id);

Тогда вам вообще не нужен триггер.

Для этого требуется, чтобы пользователь mona_internal не только получил SELECT привилегия для servis.task, но также привилегия references:

Для этого запустите следующее как пользователь SERVIS:

grant references on task to mona_internal;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...