Подтвердить что ты не робот

Пакет 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)

4b9b3361

Ответ 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;