Пакет PL/SQL недействителен
У меня есть script, который использует пакет (PKG_MY_PACKAGE). Я изменю некоторые поля в запросе в этом пакете, а затем перекомпилирую его (я не изменяю и не компилирую какие-либо другие пакеты). Я запускаю script и получаю сообщение об ошибке, которое выглядит как
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
Я снова запускаю script (не изменяя ничего в системе), и script выполняется успешно.
Я думал, что когда я скомпилировал, прежде чем я выполнил script, который исправит любые недопустимые ссылки. Это на 100% воспроизводимо, и чем больше я использую этот script, тем больше он раздражает. Что может вызвать это, и что это исправить?
(oracle 10g, используя PL/SQL Developer 7)
Ответы
Ответ 1
Фон
existing state of packages has been discarded
означает, что ваш пакет имел какое-то состояние.
Это вызвано глобальной переменной, хранящейся в вашем корпусе пакета.
До 11.2.0.2 константы также вызывают такое поведение (см. документация).
Поскольку пакет уже используется в вашей сессии, Oracle предполагает, что это состояние имеет для вас значение. Некоторые из этих переменных теперь могут иметь разные значения, а при повторной компиляции тела значения reset.
Это исключение вызывается, так что ваши клиенты знают, что больше не могут полагаться на эти переменные.
Решения
- Удалите все глобальные переменные и константы (до 11gR2) из тела пакета, если это возможно.
- Заменить глобальные переменные на функции
DETERMINISTIC
(как предложено этим ответом)
- Определение пакетов с
PRAGMA SERIALLY_REUSABLE
заставляет Oracle повторно инициализировать глобальные переменные при каждом вызове сервера.
- Закройте сеанс и снова подключите его до вызова пакета.
- Reset состояние вручную (см. ответ Павла Джеймса)
Ответ 2
Если вы запускаете файлы в script, попробуйте эти команды там перед запуском перекомпилированного кода.
exec DBMS_SESSION.RESET_PACKAGE
exec DBMS_SESSION.MODIFY_PACKAGE_STATE( DBMS_SESSION.REINITIALIZE )
Они делают то, что может предложить название.
Ответ 3
Возможные проблемы, которые могут возникнуть:
-
Пакет/процедура, которую вы вызываете, недействительна (хотя она может работать, если вызвана независимо)
проверьте этот запрос, есть ли у вас запись вашего пакета или объектов, используемых в вашем пакете, в этом представлении all_objects
выберите * из all_objects, где status = 'INVALID' и owner = 'SCHEMA_NAME';
-
Проверьте, что ваш пакет имеет глобальные переменные? если да, то проверьте, не изменилась ли эта переменная другим предпочтительным сеансом, удалите эти глобальные переменные/используйте функцию
-
выполните ниже script, чтобы скомпилировать все объекты в вашей схеме
начать dbms_utility.compile_schema ( 'SCHEMA_NAME', ложь); конец;
- Последний параметр, если ни одно из вышеперечисленных действий не удаляет все процедуры/функции из вашего пакета, добавляет новую функцию и пытается запустить вашу функцию из триггера. проверьте, работает ли это, тогда ваш пакет находится в специальной блокировке. После добавления новой функции /proc это состояние снова будет действительным, а затем вы сможете добавить все свои фактические функции /procs и удалить вновь добавленную функцию /proc.
Ответ 4
Вышеупомянутая ошибка: ORA-06508: PL/SQL: не удалось найти вызываемый программный модуль.
возникает при попытке вызвать сохраненную программу, которая не может быть найдена. Возможно, программа была удалена или несовместима с изменением или скомпилирована с ошибками.
Убедитесь, что все указанные программы, включая их тела пакетов, существуют и совместимы.
Вы можете запустить этот запрос, чтобы найти недопустимые объекты, что может привести к ошибке ORA-06508:
выберите comp_id, COMP_NAME, версия, положение дел, Пространство имен, схема
из dba_registry;