Я пытался заставить этот триггер работать, но по какой-то причине он даже не активируется до того, как я обновлю/вставлю данные в таблицу. Цель этого триггера (и я должен сделать это с помощью триггеров) — гарантировать, что все записи в таблице DISCS имеют либо «L», либо «S» в атрибуте FORMAT. Если нет, запись не должна быть вставлена/обновлена.
Я попытался добавить строку, чтобы проверить, активировался ли триггер вообще (строка «buenos dias»), но, похоже, это не по какой-то причине. Я просто новичок в триггерах, и я уверен, что ошибка действительно глупая, но я просто не могу ее найти.
Код для триггера:
CREATE OR REPLACE TRIGGER FORMAT_T
BEFORE INSERT OR UPDATE OF FORMAT
ON DISCS
FOR EACH ROW
DECLARE
bad_format EXCEPTION;
BEGIN
DBMS_OUTPUT.PUT_LINE('Buenos dias.');
IF :NEW.FORMAT != 'S' AND :NEW.FORMAT != 'L' THEN
RAISE bad_format;
END IF;
EXCEPTION
WHEN bad_format THEN
DBMS_OUTPUT.PUT_LINE('Bad format, could not insert/update.');
END FORMAT_T;
После того, как я скомпилирую триггер без проблем, я попытаюсь обновить следующую строку (используя идентификатор первой строки, чтобы просто проверить ее):
UPDATE DISCS
SET FORMAT = 'W'
WHERE ID = 1;
Это должно возвращать ошибку, поскольку формат, который я обновляю, не является «L» или «S», но вместо этого строка просто обновляется без проблем и даже без появления строки «buenos dias». В таблице user_errors ошибок тоже нет.
Спасибо за вашу помощь заранее.
@WilliamRobertson что остановит ввод значения, так это исключение «bad_format», а не сообщение отладки. Технически это исключение предотвратит его ввод





Ваша проблема связана с
IF :NEW.FORMAT != 'S' AND :NEW.FORMAT != 'L' THEN
утверждение
Просто замените на
IF :NEW.FORMAT not in ('S','L') THEN
но я бы предпочел использовать контрольное ограничение:
ALTER TABLE discs
ADD CONSTRAINT chk_format CHECK (format in ('S','L'))
В этом случае база данных автоматически выдает "проверочное ограничение нарушено" при вводе символов, отличных от 'S' или 'L', без необходимости запуска.
Я использовал AND, так как условие возбуждения исключения состоит в том, что формат не соответствует ни S, ни L, то есть выполняются оба неравенства. Если я использую OR, триггер ВСЕГДА будет генерировать исключение. Дело в том, что триггер даже не срабатывает (строка "buenos dias" не печатается). Я пытался внести эти изменения, но триггер в любом случае ничего не делает. Кроме того, по заданию я должен делать это с помощью триггеров, поэтому я не могу использовать ограничения.
@alestarbucks нет, :NEW.FORMAT != 'S' OR :NEW.FORMAT != 'L' равно NOT(:NEW.FORMAT = 'S' AND :NEW.FORMAT = 'L'), как в символической логике, или общий множитель для сложения/вычитания в математике.
хорошо, спасибо за это, я обновлю эту часть кода. Однако триггер по-прежнему не срабатывает: тестовая строка не выскакивает и строка обновляется без проблем, не показывая исключение.
@alestarbucks Хорошо, отредактировано. Использование not in понятнее.
Ваш код триггера в том виде, в котором он опубликован, работает нормально. Настоящая проблема раскрывается следующим образом:
without the "buenos dias" line even popping up
Очевидно, вы работаете в среде, в которой DBMS_OUTPUT отключен. Таким образом, ОБНОВЛЕНИЕ не выполняется, как и ожидалось, вы просто не видите сообщения. Мы можем легко продемонстрировать это, удалив блок EXCEPTION из кода триггера, как этот Скрипт SQL демонстрирует.
Включение DBMS_OUTPUT зависит от вашей среды выполнения. В SQL*Plus запустите set serveroutput on. В Oracle SQL Developer выберите View > Dbms_Output и установите соединение. В PL/SQL Developer включите DBMS_OUTPUT на листе SQL. И так далее.
Между прочим, триггер — неправильный способ применить это правило. Правильный подход — определить проверочное ограничение для столбца.
alter table disks add constraint disc_format_ck
check (format in ('S', 'L'));
CREATE OR REPLACE TRIGGER FORMAT_T
BEFORE INSERT OR UPDATE
OF FORMAT
ON DISCS
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF :NEW.FORMAT not in( 'S' , 'L') THEN
raise_application_error(-20010,'Bad format, could not insert/update.');
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('OTHERS EXCEPTION');
END FORMAT_T;
ИСПОЛЬЗУЙТЕ повышение_приложения_ошибка:
поднять_приложение_ошибка(-20010,'Неверный формат, не удалось вставить/обновить.');
Сообщение отладки не остановит ввод значения. Вероятно, это должно вызвать исключение.