2010-03-23 6 views
23

J'ai un script qui utilise un paquet (PKG_MY_PACKAGE). Je vais changer certains des champs dans une requête dans ce paquet et ensuite le recompiler (je ne change pas et ne compile pas d'autres paquets). Je lance le script et je reçois une erreur qui ressemblePL/SQL Package invalidé

 
    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 

Je lance à nouveau le script (sans rien changer d'autre dans le système) et le script est exécuté avec succès.

Je pensais que lorsque j'ai compilé avant d'exécuter le script qui permettrait de corriger les références invalides. C'est reproductible à 100%, et plus j'utilise ce script, plus ça devient ennuyeux. Qu'est-ce qui pourrait causer cela, et qu'est-ce qui pourrait le réparer?

(oracle 10g, en utilisant PL/SQL Developer 7)

+0

@OMG: Je ne fais que recompiler le corps car c'est tout ce qui change. – FrustratedWithFormsDesigner

+0

Il n'y a aucune raison pour que vous utilisiez des variables globales pour cela - passez simplement à sys_context. De cette façon, vous pouvez complètement supprimer les variables globales et rendre votre paquet sans état. –

Répondre

18

Contexte

existing state of packages has been discarded signifie, que votre colis avait une sorte d'état.

Ceci est dû à une variable globale stockée dans votre corps de package. Jusqu'au 11.2.0.2, les constantes ont également causé ce comportement (voir documentation).

Étant donné que le package a déjà été utilisé dans votre session, Oracle suppose que cet état est pertinent pour vous. Certaines de ces variables peuvent avoir des valeurs différentes maintenant, et lorsque vous recompilez le corps, les valeurs sont réinitialisées.

Cette exception est levée, afin que vos clients sachent qu'ils ne peuvent plus compter sur ces variables.

Solutions

  • Retirez toutes les variables globales et les constantes (avant 11gR2) du corps Package si possible
  • Remplacer les variables globales par DETERMINISTIC fonctions (comme le suggère this answer)
  • Définition packages avec PRAGMA SERIALLY_REUSABLE oblige Oracle à réinitialiser les variables globales à chaque appel au serveur.
  • Fermez votre session et reconnectez-vous avant d'appeler à nouveau le package.
  • réinitialiser l'état manuellement (voir Paul James' answer)
+0

En effet, j'ai quelques globals! Je vais voir si je peux trouver un moyen de contourner cela, peut-être les rendre non globaux ... Y at-il un moyen d'avoir des valeurs statiques pour les procédures en PL/SQL? – FrustratedWithFormsDesigner

+0

Que voulez-vous dire par "valeurs statiques pour les procédures"? Ces variables globales sont plus ou moins des variables statiques (par session). La solution la plus simple pour vous consisterait à placer les variables globales dans l'en-tête du package au lieu du corps. L'état ne sera plus invalidé lors de la compilation du corps. Pourquoi avez-vous besoin de ces globals? –

+0

Ils contiennent des valeurs de configuration qui ne doivent être définies qu'une seule fois et qui pilotent le reste du système. Je ne voulais pas les mettre dans l'en-tête car je ne voulais pas que d'autres codes y aient accès (ils sont passés dans la procédure pertinente d'un script). Je suppose qu'ils pourraient être stockés dans une table, mais il pourrait y avoir beaucoup de lectures sur cette table si je l'ai fait. – FrustratedWithFormsDesigner

20

Si vous êtes en cours d'exécution des choses dans un script essayer ces commandes là-dedans avant d'exécuter le code recompilées ..

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

Ils font ce que le nom pourrait suggérer.

+0

Intéressant ... Je vais devoir essayer cela. – FrustratedWithFormsDesigner

+0

Man, je voudrais pouvoir marquer deux réponses comme réponse acceptée. L'un des autres développeurs a dit que cela fonctionne bien, et cela signifie que je n'ai pas à m'inquiéter de réécrire et de re-tester le code. – FrustratedWithFormsDesigner

+0

ne fonctionne pas pour moi d'autres suggestions – vakul

0

questions possibles que vous pouvez avoir est:

  • Le package/procédure que vous appelez est invalide (même si elle peut fonctionner si elle est appelée indépendamment) vérifier cette requête si vous avez une entrée de votre colis ou objets utilisé dans votre package dans ce all_objects afficher

    sélectionner * à partir de tous_objets où status = 'INVALID' et owner = 'SCHEMA_NAME';

  • Vérifiez que votre paquet a des variables globales? Si oui, alors vérifier si les variables n'est pas modifiée par une autre session de supprimer de préférence les fonctions globales des variables/utilisation

  • run ci-dessous compiler script pour tous les objets dans votre schéma

    commencent dbms_utility.compile_schema (» SCHEMA_NAME ', false); fin;

  • Dernière option si rien de ce qui précède ne fonctionne, supprimez toutes les procédures/fonctions de votre paquet, ajoutez une nouvelle fonction et essayez d'exécuter votre fonction depuis le déclencheur. vérifiez si cela fonctionne alors votre paquet est dans un verrou spécial. Après avoir ajouté une nouvelle fonction/proc, son état sera de nouveau valide et vous pourrez alors ajouter tous vos foncs/procs actuels et supprimer la fonction/proc nouvellement ajoutée.
0

Erreur ci-dessus: ORA-06508: PL/SQL: impossible de trouver l'unité de programme appelée.

est provoquée par une tentative d'appel d'un programme stocké qui n'a pas pu être trouvé. Le programme peut avoir été supprimé ou modifié de manière incompatible, ou avoir été compilé avec des erreurs.

Vérifiez que tous les programmes référencés, y compris leurs corps de package, existent et sont compatibles.

Vous pouvez exécuter cette requête pour trouver des objets non valides, ce qui peut provoquer l'erreur ORA-06508:

sélectionner COMP_ID, nom_comp, version état , espace de noms , schéma de dba_registry;

+0

Cela se lit comme il a été copié directement à partir d'une page Web de documentation Oracle. – FrustratedWithFormsDesigner