как использовать триггеры для наследования значений из другой «родительской» записи в той же таблице - PullRequest
0 голосов
/ 12 марта 2020

Я чувствую, что это один из тех сценариев "если ты осторожен, ты можешь это сделать" ios, которые Oracle просто не хочет, чтобы я это делал.

Моя проблема в том, что У меня есть одна таблица конфигурации, которую я хочу включить наследование через триггеры. Подумайте о таблице Employee со столбцом ID SUPERVISOR и «унаследованным» ИМЯ SUPERVISOR, которое заполняется автоматически при изменении идентификатора.

Я бы хотел выполнить простой поиск для получения значения из другой строки в время INS / UPD. Но Oracle отклоняется как ошибка мутирующего триггера.

Мой код по сути:

TRIGGER UPD_CHILD_RECORD
BEFORE INSERT OR UPDATE
ON MYSCHEMA.FAKE_EMPLOYEE
FOR EACH ROW
WHEN (NEW.SUPERVISOR_ID IS NOT NULL)
BEGIN
IF INSERTING OR UPDATING
THEN
    :NEW.SUPERVISOR_NAME = (
        SELECT MAX(NAME)
        FROM MYSCHEMA.FAKE_EMPLOYEE
        WHERE EMPLOYEE_ID = :NEW.SUPERVISOR_ID
    );
END IF;
END UPD_CHILD_RECORD
;

спасибо.

1 Ответ

0 голосов
/ 13 марта 2020

Это нормальное поведение. Oracle защищает вас от противоречивых данных, которые вы можете получить при доступе к таблице, которая уже обновляется.

Представьте себе этот сценарий.
Вы отправляете два оператора обновления и имеете триггер, который выбирает из этой же таблицы. Предположим, что первое утверждение успешно применено, а данные изменены. Теперь пришло время для второго заявления. Какой вывод вы ожидаете от оператора выбора в триггере? Должен ли он возвращать данные, которые были до первого обновления, или он должен включать внесенные изменения? Вы, вероятно, думаете, что Oracle должен вернуть новые данные. Но, во-первых, Oracle на самом деле не знает ваших намерений, а во-вторых, это будет означать, что ваш запрос зависит от порядка строк, что противоречит реляционной алгебре.

Решение вашей проблемы довольно простое. Вам вообще не нужен столбец SUPERVISOR_NAME. Чтобы получить имя супервизора, просто объедините таблицу с самим собой и получите желаемый результат, например:

select t1.ID, t1.SUPERVISOR_ID, t2.NAME from FAKE_EMPLOYEE t1
    left join FAKE_EMPLOYEE t2 on t1.SUPERVISOR_ID = t2.ID;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...