При сохранении данных (выполнение COMMIT в триггере
или нажатие пользователем на [Сохранить]),
Oracle Forms иногда выдает ошибку FRM-40401,
но изменения при этом сохраняются.
При выполнении POST может появиться похожее сообщение
"FRM-40405: Нет обновлений, кот. следует принять."
Как избежать появления подобных сообщений?
Ответ на этот вопрос необходимо разбить на две части.
Во-первых, нужно разобраться в причинах появления этого сообщения.
И во-вторых, рассмотреть возможные способы "борьбы" с появлением
подобных, впрочем как и любых других, сообщений Oracle Forms.
Итак.
FRM-40401
FRM-40401Причину появления любого системного сообщения, а также возможные действия, которые нужно в связи с этим предпринять, можно получить в справочной системе Oracle Forms.
Если обратиться к этой системе, то для FRM-40401
можно обнаружить (в моей интерпретации) следующее:
| Причина (Cause) | Отсутствуют записи, добавленные или измененные с
момента последнего применения(POST)
или сохранения(COMMIT).
|
| Действия (Action) | Действия не требуются. |
То есть, с момента последнего сохранения изменений,
записи в блоках данных (блоки со свойством Database Data Block = Yes)
не изменялись и Forms-у не нужно генерировать команды
INSERT, UPDATE, DELETE, о чем он нам и сообщает.
Я специально выделил "записи в блоках данных",
т.к. отсутствие изменений именно в них имеется ввиду в тексте сообщения
об ошибке FRM-40401.
Но имеется еще один тип изменений, которые возможно произвести
в Oracle Forms.
Можно напрямую записать команды INSERT, UPDATE, DELETE
в триггеры формы, не участвующие в процессе сохранения данных,
скажем в WHEN-BUTTON-PRESSED.
Также, из таких триггеров можно вызывать хранимые процедуры,
выполняющие изменения в базе данных.
Более того, именно такого рода изменения вы и пытаетесь сохранить, иначе, сообщение FRM-40401 и не появлялось бы.
На этой стадии ответа, с учетом изложенного выше, позвольте переформулировать исходный вопрос:
"Так почему же появляется это сообщение. Мы сделали напрямую
изменения в базе данных и тут же пытаемся их сохранить.
Мы просто выполняем COMMIT, нам не нужно обрабатывать изменения
в блоках данных."
Когда Oracle Forms встречает в тексте триггера COMMIT,
он автоматически заменяет эту команду на встроенную подпрограмму
COMMIT_FORM (также как и ROLLBACK
на CLEAR_FORM).
COMMIT_FORM же, в свою очередь, не просто выполняет
COMMIT. Эта процедура предварительно проверяет статус формы
и при необходимости выполнения изменений, для каждого блока данных
формирует и выполняет требуемые команды DELETE, UPDATE, INSERT
(кстати, именно в таком порядке).
Если изменений не было - получаем FRM-40401.
И только после этого выпоняется "настоящий" COMMIT,
сохраняющий, в том числе, и изменения в форме сделанные напрямую.
Встречный вопрос.
А теперь попробуйте объяснить, почему при выполнении
FORMS_DDL('COMMIT'), взамен просто COMMIT ,
и изменения сохраняются, и FRM-40401 не появляется.
Разработчики продукта Oracle Forms не рекомендуют производить прямые изменения в базе данных в триггерах не задействованных при сохранении данных. Однако, нужно признать, что необходимость в них все-таки бывает, и поэтому нам нужны способы "избавления" от появления этого сообщения.
Давайте же их рассмотрим.
Помимо частного случая с FORMS_DDL('COMMIT')
(частного для FRM-40401),
существует два способа обработки любых сообщений Oracle Forms.
Предостережение об использовании
FORMS_DDL('COMMIT').
Ни в коем случае не используйте эту команду, без полного
понимания того, что она делает!!!
Например, нужно точно понимать отличия FORMS_DDL('COMMIT')
от процедуры commit2 приведенной ниже
SYSTEM.MESSAGE_LEVELКаждому системному сообщению назначен, так называемый, уровень серьезности (severity level). Всего существует 6 уровней: 5, 10, 15, 20, 25, >25
Узнать уровень конкретного сообщения можно в справочной системе.
Для этого откройте Help->Form Builder Help Topics (Ctrl+H) и на закладке
'Поиск' введите, например, 'FRM-40401'.
Помимо упомянутых выше Причины(Cause) и Действий(Action), здесь можно увидеть Уровень(Level) и Тип сообщения(Type) (тип нам понадобиться позже).
Теперь о системной переменной SYSTEM.MESSAGE_LEVEL.
Если в процессе работы формы, требуется вывести сообщение,
то оно будет выведено только в том случае, если уровень этого
сообщения больше чем значение SYSTEM.MESSAGE_LEVEL.
В противном случае, сообщение будет проигнорировано.
По умолчанию, значение SYSTEM.MESSAGE_LEVEL равно '0',
и это значит, что Oracle Forms будет выводить любые сообщения.
Исходя из списка возможных уровней, мы имеем 6 значений,
которые имеет смысл присваивать переменной SYSTEM.MESSAGE_LEVEL
(одна из немногих системных переменных, которым можно присваивать значения):
0, 5, 10, 15, 20, 25
Присвоение переменной SYSTEM.MESSAGE_LEVEL значения 10
будет означать, что все сообщения, имеющие уровень 5 или 10,
больше выводиться не будут.
Нет никакого смысла, хотя и не будет ошибкой, присваивать этой переменной значения типа 12 или 14. Можно обойтись 10 - эффект тот же (Строго говоря, ошибкой будет присвоение значения не из диапазона 0 .. 25).
Сообщения имеющие уровень '>25' подавить нельзя. Это, как правило, сообщения о грубых ошибках в программе.
Имея ввиду всё сказанное выше, а также информацию о том, что уровень
сообщения FRM-40401 равен 5, можно написать простую процедуру,
которая будет сохранять изменения в форме и при этом "не ругаться":
PROCEDURE commit2
IS
BEGIN
IF TO_NUMBER(NAME_IN('SYSTEM.MESSAGE_LEVEL')) < 5
THEN
COPY ('5', 'SYSTEM.MESSAGE_LEVEL');
COMMIT;
COPY ('0', 'SYSTEM.MESSAGE_LEVEL');
ELSE
COMMIT;
END IF;
END commit2;
Теперь после выполнения прямых изменений в форме вместо
COMMIT можно использовать commit2
Примечание.
Это лишь образец процедуры. Сюда же можно добавить выполнение
не только COMMIT, но и POST,
а также проверку статуса завершения.
ON-ERROR, ON-MESSAGEЭтот способ позволяет не просто подавить сообщение, он
позволяет его перехватить и выполнить любые требуемые действия
(в том числе и ничего не делать, если нам всё-таки нужно подавить сообщение).
Некий аналог секции EXCEPTION языка PL/SQL.
Выше уже упоминалось, что для каждого сообщения в справочной системе определён тип. Существует два типа сообщений:
Для перехвата системных сообщений Oracle Forms используются триггеры:
ON-ERROR для сообщений об ошибке и
ON-MESSAGE - для информационных сообщений.
Возвращаясь к FRM-40401, видно что это сообщение об ошибке,
следовательно для его перехвата нужно использовать триггер
ON-ERROR:
/* 40401 возникает при COMMIT, 40405 - при POST */ IF ERROR_CODE IN (40401, 40405) THEN NULL; -- либо требуемые действия ELSE MESSAGE (ERROR_TYPE || '-' || ERROR_CODE || ': ' || ERROR_TEXT); RAISE FORM_TRIGGER_FAILURE; END IF;
Фраза ELSE в этом триггере выполняет стандартные
действия Oracle Forms для всех прочих сообщений об ошибках.
Ну и не нужно забывать, что триггеры ON-ERROR и
ON-MESSAGE могут быть определены на всех трех уровнях:
элемента, блока, формы.
11 Июня 2003г.