2010-03-23 19 views
23

Tengo un script que hace uso de un paquete (PKG_MY_PACKAGE). Voy a cambiar algunos de los campos en una consulta en ese paquete y luego recompilarlo (no cambio ni compilo ningún otro paquete). Corro el guión y me sale un error que se parece aPaquete PL/SQL invalidado

 
    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 

corro el script de nuevo (sin cambiar nada más en el sistema) y la secuencia de comandos se ejecuta correctamente.

Pensé que cuando compilé antes de ejecutar el script que solucionaría las referencias no válidas. Esto es 100% reproducible, y cuanto más uso este script, más molesto se vuelve. ¿Qué podría causar esto y qué lo solucionaría?

(Oracle 10g, usando PL/SQL Developer 7)

+0

@OMG: Solo estoy recompilando el cuerpo porque eso es todo lo que cambia. – FrustratedWithFormsDesigner

+0

No hay ninguna razón para que use variables globales para esto; solo cambie a sys_context. De esta forma, puede eliminar completamente las variables globales y hacer que su paquete sea sin estado. –

Respuesta

18

Antecedentes

existing state of packages has been discarded medios, que su paquete tenía algún tipo de estado.

Esto se debe a una variable global almacenada en su cuerpo de paquete.
Hasta 11.2.0.2, las constantes también causaron este comportamiento (consulte documentation).

Dado que el paquete ya se ha utilizado en su sesión, Oracle asume que este estado es relevante para usted. Algunas de estas variables pueden tener valores diferentes ahora, y cuando recompila el Cuerpo, los valores se restablecen.

Se emite esta excepción, para que sus clientes sepan que ya no pueden confiar en esas variables.

Soluciones

  • Quitar todas las variables globales y constantes (antes 11gR2) del cuerpo del paquete, si es posible
  • Reemplazar variables globales por DETERMINISTIC funciones (como se sugiere por this answer)
  • Definición los paquetes con PRAGMA SERIALLY_REUSABLE hacen que Oracle reinicialice las variables globales con cada llamada al servidor.
  • Cierre su sesión y reconéctese antes de volver a llamar al paquete.
  • Restablecer el estado manualmente (ver Paul James' answer)
+0

De hecho, ¡tengo algunos globales! Veré si puedo encontrar una forma de evitar eso, tal vez hacer que no sean globales ... ¿Hay alguna manera de tener valores estáticos para los procedimientos en PL/SQL? – FrustratedWithFormsDesigner

+0

¿Qué quiere decir exactamente con "valores estáticos para procedimientos"? Esas variables globales son variables más o menos estáticas (por sesión). La solución más fácil para usted sería colocar las variables globales en el encabezado del paquete en lugar del cuerpo: el estado ya no se invalidará al compilar el cuerpo. ¿Por qué necesitas esos globals? –

+0

Tienen valores de configuración que solo necesitan establecerse una vez y controlar el resto del sistema. No quería ponerlos en el encabezado porque no quería que ningún otro código tuviera acceso a ellos (se pasan al único procedimiento relevante de un script). Supongo que podrían almacenarse en una tabla, pero podría haber MUCHAS lecturas en esa tabla si lo hiciera. – FrustratedWithFormsDesigner

20

Si está ejecutando un script cosas en tratar estos comandos en allí antes de ejecutar el nuevo código compilado ..

exec DBMS_SESSION.RESET_PACKAGE 
exec DBMS_SESSION.MODIFY_PACKAGE_STATE(DBMS_SESSION.REINITIALIZE) 

Hacen qué podría sugerir el nombre

+0

Interesante ... Tendré que probar esto. – FrustratedWithFormsDesigner

+0

Hombre, desearía poder marcar dos respuestas como la respuesta aceptada. Uno de los desarrolladores aquí dijo que esto funciona bien, y significa que no tengo que preocuparme por volver a escribir y volver a probar el código. – FrustratedWithFormsDesigner

+0

no funciona para mí ninguna otra sugerencia – vakul

0

Posibles problemas que puede tener es:

  • El paquete/procedimiento que está llamando no es válido (aunque puede funcionar si se llama de forma independiente) cheque esta consulta si tiene una entrada de su paquete u objetos usado en su paquete en este all_objects view

    select * from all_objects where status = 'INVALID' y owner = 'SCHEMA_NAME';

  • ¿Comprueba que su paquete tenga variables globales? Si sí, entonces comprobar si esas variables no está siendo cambiada por cualquier otra sesión de eliminar aquellos preferible función global de variables/uso

  • plazo por debajo de secuencia de comandos para compilar todos los objetos en el esquema

    comienzan dbms_utility.compile_schema (' SCHEMA_NAME ', falso); final;

  • Última opción, si ninguna de las opciones anteriores funciona, elimine todos los procedimientos/funciones de su paquete, agregue una nueva función e intente ejecutar su función desde el desencadenador. compruebe si esto funciona, entonces su paquete está en un bloqueo especial. Después de agregar una nueva función/proc, su estado volverá a ser válido y luego podrá agregar todos sus funcs/procs reales y eliminar la nueva función/proc añadida.
0

El error anterior: ORA-06508: PL/SQL: no se pudo encontrar la unidad de programa que se está llamando.

se produce cuando se intentó llamar a un programa almacenado que no se pudo encontrar. Es posible que el programa se haya eliminado o se haya modificado de forma incompatible, o que se haya compilado con errores.

Compruebe que todos los programas a los que se hace referencia, incluidos sus cuerpos de paquete, existen y son compatibles.

Puede ejecutar esta consulta para encontrar los objetos no válidos, lo que puede provocar el error ORA-06508:

seleccionar comp_id, COMP_NAME, versión , estado, espacio de nombres, esquema de dba_registry;

+0

Esto parece que fue copiado directamente de una página web de documentación de Oracle. – FrustratedWithFormsDesigner

Cuestiones relacionadas