У меня есть сценарий, который использует пакет (PKG_MY_PACKAGE). Я изменю некоторые поля в запросе в том пакете и затем перекомпилирую его (я не изменяю или компилирую любые другие пакеты). Я запускаю скрипт, и я получаю ошибку, которая похожа
ORA-04068: existing state of packages has been discarded ORA-04061: existing state of package body "USER3.PKG_MY_PACKAGE" has been invalidated ORA-04065: not executed, altered or dropped package body "USER3.PKG_MY_PACKAGE" ORA-06508: PL/SQL: could not find program unit being called: "USER3.PKG_MY_PACKAGE" ORA-06512: at line 34
Я запускаю скрипт снова (не изменяя ничто больше в системе), и сценарий выполняется успешно.
Я думал что, когда я скомпилировал, прежде чем я выполнил сценарий, который зафиксирует любые недопустимые ссылки. Это на 100% восстанавливаемо, и чем больше я использую этот сценарий, тем более раздражающим это становится. Что могло вызвать это, и что зафиксирует его?
(оракул 10 г, с помощью МН Разработчика / Разработчика SQL 7)
Background
существующее состояние пакетов было отброшено
означает, что у вашего пакета было какое-то состояние.
Это вызвано глобальной переменной, хранящейся в теле вашего пакета.
До версии 11.2.0.2 константы также вызывали такое поведение (см. документацию).
Поскольку пакет уже использовался в вашей сессии, Oracle предполагает, что это состояние актуально для вас. Некоторые из этих переменных могут иметь другие значения сейчас, и когда вы перекомпилируете тело, значения будут сброшены.
Это исключение выбрасывается, чтобы ваши клиенты знали, что они больше не могут полагаться на эти переменные.
Решения
DETERMINISTIC
(как предлагается в этом ответе)PRAGMA SERIALLY_REUSABLE
заставляет Oracle заново инициализировать глобальные переменные при каждом обращении к серверу. Если вы запускаете что-то в сценарии, попробуйте эти команды там, прежде чем запускать повторно скомпилированный код ..
exec DBMS_SESSION.RESET_PACKAGE
exec DBMS_SESSION.MODIFY_PACKAGE_STATE( DBMS_SESSION.REINITIALIZE )
Они делают то, что может подсказывать название.