Ответ 1
Несколько вопросов в определенном порядке.
Во-первых, в теле триггера уровня вам нужно использовать :new
и :old
для ссылки на новые и старые записи. Требуется ведущая ободочная кишка. Таким образом, ваше предложение WHERE
должно быть
WHERE PROJECTID = :new.PROJECTID
Во-вторых, если вы используете CREATE TRIGGER
в SQL * Plus, вы можете получить список ошибок и предупреждений с помощью команды SHOW ERRORS
, т.е.
SQL> show errors
Вы также можете запросить таблицу DBA_ERRORS
(или ALL_ERRORS
или USER_ERRORS
в зависимости от вашего уровня привилегий), но это не то, что вам обычно нужно прибегать.
В-третьих, если исправить ошибки синтаксиса, вы получите мутирующую ошибку таблицы, если вы используете эту логику. Триггер уровня строки в таблице A (TPM_TRAININGPLAN
в этом случае) не может запрашивать таблицу A, потому что таблица может находиться в несогласованном состоянии. Вы можете обойти это, как показывает Тим в своей статье, создав пакет с коллекцией, инициализируя эту коллекцию в триггере перед запуском, заполняя данные в коллекции триггером уровня, а затем обрабатывая измененные строки в триггер после утверждения. Тем не менее, сложная сложность для добавления в систему, поскольку вам придется управлять несколькими различными объектами.
Как правило, вам лучше реализовать эту логику как часть любого API, который вы используете для управления таблицей TPM_TRAININGPLAN
. Если это хранимая процедура, имеет смысл добавить логику для обновления TPM_PROJECT
в этой хранимой процедуре, а не поместить ее в триггер. Как правило, больно пытаться отлаживать приложение, в котором много логики встроено в триггеры, потому что разработчикам очень сложно следить за тем, какие операции выполняются. В качестве альтернативы вы можете удалить столбец TRAININGDELIVERYSTART
из таблицы TPM_PROJECT
и просто вычислить минимальную дату начала во время выполнения.
В-четвертых, если ваш триггер срабатывает при вставках, обновлениях и удалениях, вы не можете просто ссылаться на значения :new
. :new
действителен для вставок и обновлений, но он будет NULL, если вы делаете удаление. :old
действителен для удалений и обновлений, но будет иметь значение NULL, если вы делаете вставку. Это означает, что вы, вероятно, должны иметь логику вдоль линий (ссылаясь на решение пакета Tim)
BEGIN
IF inserting
THEN
trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
ELSIF updating
THEN
trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
ELSIF deleting
THEN
trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
END IF;
END;