2010-02-02 3 views
7

Ich versuche, eine Liste der PL/SQL-Paketabhängigkeiten aufzubauen, damit ich ein automatisiertes Build-Skript für meine Pakete auf dem Testserver ausführen kann. Gibt es eine Möglichkeit, mit einem einzelnen Paket (einem "root" -Paket, das idealerweise namentlich identifiziert wird) zu beginnen und dann alle Abhängigkeiten und die Reihenfolge zu finden, in der sie kompiliert werden müssen? Abhängigkeiten sind bereits vollständig in meinem persönlichen Schema gelöst (so muss ich zumindest irgendwo anfangen - aber wohin gehe ich als nächstes?).Oracle Build-Reihenfolge und PL/SQL-Paket Abhängigkeiten

(Oracle 10,2)

EDIT:

Das Build-Tool, das verwendet wird, um die Erstellungsreihenfolge verwenden und diese Dateien in der Reihenfolge von Quellensteuerung, retreive und dann an Oracle gibt sie an kompilieren (das eigentliche Build-Tool selbst ist in Python oder Java oder beides geschrieben - ich habe keinen Zugriff auf die Quelle). Im Grunde benötigt das Build-Tool eine Liste von Dateien, die kompiliert werden müssen, um in der Reihenfolge zu kompilieren, in der sie in kompiliert werden müssen, und Zugriff auf diese Dateien in der Quellcodeverwaltung. Wenn es das hat, wird alles ganz gut funktionieren.

EDIT:

Danke für die ordentlich Skripte. Leider liegt der Build-Prozess größtenteils außerhalb meiner Hände. Der Prozess basiert auf einem Build-Tool, das vom Hersteller des Produkts, mit dem wir arbeiten, erstellt wurde. Aus diesem Grund kann ich dem Build-Prozess nur eine Liste von Dateien in der Reihenfolge geben, in der sie erstellt werden müssen. Wenn ein Compilerfehler auftritt, schlägt das Build-Tool fehl, wir müssen manuell eine Anfrage für einen neuen Build einreichen. Daher ist eine Liste von Dateien in der Reihenfolge wichtig, in der sie kompiliert werden sollten.

EDIT:

Gefunden dies: http://www.oracle.com/technology/oramag/code/tips2004/091304.html Gibt mir die Abhängigkeiten eines Objekts. Jetzt muss ich nur noch Ordnung schaffen ... Wenn etwas funktioniert, werde ich es hier posten.

EDIT: (! Mit Code)

Ich weiß, dass in der Regel diese Art der Sache für Oracle nicht erforderlich ist, sondern für jeden, der nach wie vor interessiert ...

Ich habe zusammengeschustert ein kleines Skript, das das erste Mal in der richtigen Reihenfolge ohne Abhängigkeitsfehler gebaut werden eine Build-Reihenfolge, so dass alle Pakete bekommen zu können, scheint sein (zu Pacakges in Bezug):

declare 

    type t_dep_list is table of varchar2(40) index by binary_integer; 
    dep_list t_dep_list; 
    i number := 1; 
    cursor c_getObjDepsByNameAndType is 
    --based on a query found here: http://www.oracle.com/technology/oramag/code/tips2004/091304.html 
     select lvl, u.object_id, u.object_type, LPAD(' ', lvl) || object_name obj 
     FROM (SELECT level lvl, object_id 
       FROM SYS.public_dependency s 
       START WITH s.object_id = (select object_id 
             from user_objects 
             where object_name = UPPER(:OBJECT_NAME) 
               and object_type = UPPER(:OBJECT_TYPE)) 
       CONNECT BY s.object_id = PRIOR referenced_object_id 
       GROUP BY level, object_id) tree, user_objects u 
     WHERE tree.object_id = u.object_id 
       and u.object_type like 'PACKAGE%' --only look at packages, not interested in other types of objects 
     ORDER BY lvl desc; 

    function fn_checkInList(in_name in varchar2) return boolean is 
    begin 
     for j in 1 .. dep_list.count loop 
      if dep_list(j) = in_name then 
       return true; 
      end if; 
     end loop; 
     return false; 
    end; 



    procedure sp_getDeps(in_objID in user_objects.object_id%type, in_name in varchar2) is 
     cursor c_getObjDepsByID(in_objID in user_objects.object_id%type) is 
     --based on a query found here: http://www.oracle.com/technology/oramag/code/tips2004/091304.html 
      select lvl, u.object_id, u.object_type, LPAD(' ', lvl) || object_name obj 
      FROM (SELECT level lvl, object_id 
        FROM SYS.public_dependency s 
        START WITH s.object_id = (select uo.object_id 
              from user_objects uo 
              where uo.object_name = 
                (select object_name from user_objects uo where uo.object_id = in_objID) 
                and uo.object_type = 'PACKAGE BODY') 
        CONNECT BY s.object_id = PRIOR referenced_object_id 
        GROUP BY level, object_id) tree, user_objects u 
      WHERE tree.object_id = u.object_id 
        and u.object_id <> in_objID --exclude self (requested Object ID) from list. 
      ORDER BY lvl desc; 
    begin 
     --loop through the dependencies 
     for r in c_getObjDepsByID(in_objID) loop 
      if fn_checkInList(trim(r.obj)) = false and (r.object_type = 'PACKAGE' or r.object_type = 'PACKAGE BODY') and 
       trim(r.obj) <> trim(in_name) then 
       dbms_output.put_line('checking deps of: ' || r.obj || ' ' || r.object_id || ' level: ' || r.lvl); 
       --now for each dependency, check the sub-dependency 
       sp_getDeps(r.object_id, trim(r.obj)); 
       --add the object to the dependency list. 
       dep_list(i) := trim(r.obj); 
       i := i + 1; 
      end if; 
     end loop; 
    exception 
     when NO_DATA_FOUND then 
      dbms_output.put_line('no more data for: ' || in_objID); 
    end; 

begin 

    for r in c_getObjDepsByNameAndType loop 
     dbms_output.put_line('top-level checking deps of: ' || r.obj || ' ' || r.object_id || ' level: ' || r.lvl); 
     sp_getDeps(r.object_id, trim(r.obj)); 
    end loop; 

    dbms_output.put_line('dep count: ' || dep_list.count); 
    for j in 1 .. dep_list.count loop 
     dbms_output.put_line('obj: ' || j || ' ' || dep_list(j)); 
    end loop; 
end; 

ich weiß, es ist nicht der hübscheste Code (Globals überall, etc ... ugh), und ich werde es wahrscheinlich erneut veröffentlichen, wenn ich heute Nachmittag die Chance bekomme, es aufzuräumen, aber im Moment produziert es eine Build-Reihenfolge, die scheint das erste Mal ohne Probleme zu laufen.

:OBJECT_NAME sollte das Stammobjekt sein, das Sie alle Abhängigkeiten verfolgen und Reihenfolge von erstellen möchten. Für mich ist dies ein Hauptpaket mit einer einzigen Methode, die den Einstiegspunkt für den Rest des Systems darstellt.

:OBJECT_TYPE Ich habe meist auf PACKAGE BODY beschränkt, aber es sollte nicht zu viel Arbeit sein, um andere Arten, wie zum Beispiel Trigger.

Eine letzte Sache, das Objekt von :OBJECT_NAME angegeben wird nicht in der Ausgabe angezeigt, aber es sollte das letzte Element sein, also müssen Sie das zu Ihrer Build-Liste manuell hinzufügen.

UPDATE: Ich habe gerade entdeckt user_dependencies und all_dependencies könnte dieser Code wahrscheinlich jetzt viel einfacher gemacht werden.

+0

meinen Sie Oracle PL/SQL-Pakete? –

+0

Ich habe es nur gemacht, um es zu skripten und die Bereitstellung in einem neuen Schema zu testen. Ordnen Sie die Pakete im Skript nach Bedarf neu an, basierend auf Fehlern ... –

+0

Ja, ich meinte Pakete. – FrustratedWithFormsDesigner

Antwort

-1

Aktuelle Lösung: Das obige Skript scheint die richtige Build-Reihenfolge zu geben. Könnte wahrscheinlich umgeschrieben werden "netter", aber ich überlasse das als eine Übung für den Leser. ;)

Nach einiger Diskussion wird das Build-Tool n (4, tatsächlich) in einer Reihe vor dem Melden von Fehlern erstellt. Dies würde auch dazu beitragen, Fehler bei der Kompilierung von Abhängigkeiten zu beheben, wenn die Build-Reihenfolge falsch ist, aber ich möchte die Build-Reihenfolge lieber gleich beim ersten Mal korrigieren.

2

Blick auf das folgende Skript von http://www.oracle-base.com/articles/misc/RecompilingInvalidSchemaObjects.php

SET SERVEROUTPUT ON SIZE 1000000 
BEGIN 
    FOR cur_rec IN (SELECT owner, 
         object_name, 
         object_type, 
         DECODE(object_type, 'PACKAGE', 1, 
              'PACKAGE BODY', 2, 2) AS recompile_order 
        FROM dba_objects 
        WHERE object_type IN ('PACKAGE', 'PACKAGE BODY') 
        AND status != 'VALID' 
        ORDER BY 4) 
    LOOP 
    BEGIN 
     IF cur_rec.object_type = 'PACKAGE' THEN 
     EXECUTE IMMEDIATE 'ALTER ' || cur_rec.object_type || 
      ' "' || cur_rec.owner || '"."' || cur_rec.object_name || '" COMPILE'; 
     ElSE 
     EXECUTE IMMEDIATE 'ALTER PACKAGE "' || cur_rec.owner || 
      '"."' || cur_rec.object_name || '" COMPILE BODY'; 
     END IF; 
    EXCEPTION 
     WHEN OTHERS THEN 
     DBMS_OUTPUT.put_line(cur_rec.object_type || ' : ' || cur_rec.owner || 
          ' : ' || cur_rec.object_name); 
    END; 
    END LOOP; 
END; 
/
+0

Interessant, aber ich bin nicht sicher, dass dies eine tatsächliche Build-Reihenfolge bereitstellen wird. – FrustratedWithFormsDesigner

0

Sie brauchen nicht einen Auftrag zu bauen - nur die Pakete bauen mit „CREATE OR REPLACE ...“ auf einer Datei-für-Datei-Basis und dann kompilieren Sie sie in einer zweistufigen Nested-Schleife - jeder Durchlauf in der inneren Schleife kompiliert alles, was noch ungültig ist, und die äußere Schleife wird verwendet, um die Anzahl der verbleibenden ungültigen Objekte zu überprüfen und eine Art Schwellenwert für maximale Ausführungen der inneren Schleife festzulegen. In der Praxis habe ich nie gesehen, dass die Anzahl der benötigten Pässe höher als drei ist.

Wenn Sie mehrere Schemas in die Abhängigkeiten einbezogen haben, schauen Sie in laufendes Oracles-Skript utlrp.sql, das schemasübergreifend funktioniert und eine Infrastruktur zur Verwaltung des Prozesses einrichtet - dies erfordert jedoch einen privilegierten Account.

Wenn Sie die Quellcodeverwaltung auch um Ansichten erweitern, müssen Sie sicherstellen, dass die Skripts "CREATE OR REPLACE FORCE VIEW ..." verwenden, um Ansichten zu erstellen, deren Abhängigkeiten zum Zeitpunkt der Erstellung nicht erfüllt sind.

Beispiel-Skript, das ich benutze:

set serveroutput on 
declare 
cursor invalidObjCur is 
    select object_name, object_type 
    from user_objects 
    where status <> 'VALID' 
    ; 
compileStmt varchar2(4000); 
passCount pls_integer := 0; 
maxPasses pls_integer := 5; 
lastInvalidCount pls_integer := 32000; 
objectCount pls_integer; 
continue boolean := TRUE; 

begin 
dbms_output.enable(1000000); 
while (continue) loop 
    passCount := passCount + 1; 
    dbms_output.put_line('Pass '||passCount); 
    objectCount := 0; 
    for curRow in InvalidObjCur loop 
    if curRow.object_type = 'PACKAGE BODY' then 
     compileStmt := 'alter PACKAGE '||curRow.object_name||' compile body'; 
    else 
     compileStmt := 'alter '||curRow.object_type||' '|| 
     chr(34)||curRow.object_name||chr(34)||' compile'; 
    end if; 
    begin 
     execute immediate compileStmt; 
    exception when others then 
     null; 
    end; 
    objectCount := objectCount + 1; 
    end loop; 
    dbms_output.put_line('Recompilations attempted: '||objectCount); 
    continue := (passCount < maxPasses) and (objectCount < lastInvalidCount); 
    lastInvalidCount := objectCount; 
end loop; 
dbms_output.put_line('***** Remaining Invalid ********'); 
for curRow in InvalidObjCur loop 
dbms_output.put_line(curRow.object_type||' '||curRow.object_name); 
end loop; 
dbms_output.put_line('********************************'); 
end;  
/
8

Wenn Sie wirklich nur mit PL/SQL-Pakete zu tun Sie nicht brauchen, um die Build-Reihenfolge zu schwitzen. Erstellen Sie zuerst alle Paketspezifikationen. Dann können Sie alle Paketkörper bereitstellen und sie werden kompiliert, da ihre Abhängigkeiten die Paketspezifikationen sind.

Wenn Sie einige Paketspezifikationen haben, die von anderen Spezifikationen abhängen - wenn Sie Pakete haben, die z. B. Konstanten, Subtypen oder Ref-Cursor deklarieren, die in den Signaturen von Paketprozeduren verwendet werden, müssen Sie diese erstellen Paketspezifikationen zuerst. Aber es sollte wenige genug von ihnen geben, dass Sie sie im Build-Skript von Hand anordnen können.

bearbeiten

Es sieht aus wie sie baut tun wil inkrementelle und „Clean-Sweep“, so die Build-Reihenfolge werden die meisten für Rolle, wenn sie die Umgebung reinigen und sie wieder aufbauen .

Das ändert nichts.

Hier ist ein erweitertes Beispiel. Ich habe ein Schema mit drei Paketen ....

SQL> select object_name, object_type, status 
    2 from user_objects 
    3 order by 1, 2 
    4/

OBJECT_NAME  OBJECT_TYPE  STATUS 
--------------- --------------- ------- 
PKG1   PACKAGE   VALID 
PKG1   PACKAGE BODY VALID 
PKG2   PACKAGE   VALID 
PKG2   PACKAGE BODY VALID 
PKG3   PACKAGE   VALID 
PKG3   PACKAGE BODY VALID 

6 rows selected. 

SQL> 

Das Interessante daran ist, dass ein Verfahren in PKG1 eine Prozedur aus PKG2 nennt, ein Verfahren in PKG2 eine Prozedur aus PKG3 ruft und ein Verfahren in PKG3 ruft eine Prozedur von PKG1.

Q. Wie funktioniert diese zirkuläre Abhängigkeit?
A. Es ist nicht eine zirkuläre Abhängigkeit ....

SQL> select name, type, referenced_name, referenced_type 
    2 from user_dependencies 
    3 where referenced_owner = user 
    4/

NAME   TYPE   REFERENCED_NAME REFERENCED_TYPE 
--------------- --------------- --------------- --------------- 
PKG1   PACKAGE BODY PKG1   PACKAGE 
PKG1   PACKAGE BODY PKG2   PACKAGE 
PKG2   PACKAGE BODY PKG2   PACKAGE 
PKG2   PACKAGE BODY PKG3   PACKAGE 
PKG3   PACKAGE BODY PKG3   PACKAGE 
PKG3   PACKAGE BODY PKG1   PACKAGE 

6 rows selected. 

SQL> 

Alle abhängigen Objekte die Paketkörper sind, werden alle referenzierten Objekte sind die verpackten Spezifikationen. Folglich, wenn ich das Schema nicht neu baue, ist es egal, welche Reihenfolge ich verwende. Erste Müll wir ...

SQL> drop package pkg1 
    2/

Package dropped. 

SQL> drop package pkg2 
    2/

Package dropped. 

SQL> drop package pkg3 
    2/

Package dropped. 

SQL> 

Dann wieder aufbauen wir ...

SQL> create or replace package pkg3 is 
    2  procedure p5; 
    3  procedure p6; 
    4 end pkg3; 
    5/

Package created. 

SQL> create or replace package pkg2 is 
    2  procedure p3; 
    3  procedure p4; 
    4 end pkg2; 
    5/

Package created. 

SQL> create or replace package pkg1 is 
    2  procedure p1; 
    3  procedure p2; 
    4 end pkg1; 
    5/

Package created. 

SQL> create or replace package body pkg2 is 
    2  procedure p3 is 
    3  begin 
    4   pkg3.p5; 
    5  end p3; 
    6  procedure p4 is 
    7  begin 
    8   dbms_output.put_line('PKG2.P4'); 
    9  end p4; 
10 end pkg2; 
11/

Package body created. 

SQL> create or replace package body pkg3 is 
    2  procedure p5 is 
    3  begin 
    4   dbms_output.put_line('PKG3.P5'); 
    5  end p5; 
    6  procedure p6 is 
    7  begin 
    8   pkg1.p1; 
    9  end p6; 
10 end pkg3; 
11/

Package body created. 

SQL> create or replace package body pkg1 is 
    2  procedure p1 is 
    3  begin 
    4   dbms_output.put_line('PKG1.P1'); 
    5  end p1; 
    6  procedure p2 is 
    7  begin 
    8   pkg2.p4; 
    9  end p2; 
10 end pkg1; 
11/

Package body created. 

SQL> 

Die Reihenfolge der einzelnen Objekte nicht relevant ist. Erstellen Sie einfach die Paketspezifikationen vor den Paketkörpern. Obwohl auch wirklich nicht, dass keine Rolle ...

SQL> create or replace package pkg4 is 
    2  procedure p7; 
    3 end pkg4; 
    4/

Package created. 

SQL> create or replace package body pkg4 is 
    2  procedure p7 is 
    3  begin 
    4   dbms_output.put_line('PKG4.P7::'||constants_pkg.whatever); 
    5  end p7; 
    6 end pkg4; 
    7/

Warning: Package Body created with compilation errors. 

SQL> show errors 
Errors for PACKAGE BODY PKG4: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
4/9  PL/SQL: Statement ignored 
4/43  PLS-00201: identifier 'CONSTANTS_PKG.WHATEVER' must be declared 
SQL> 

PKG4 ist ungültig, weil wir CONSTANTS_PKG noch nicht gebaut haben.

SQL> create or replace package constants_pkg is 
    2  whatever constant varchar2(20) := 'WHATEVER'; 
    3 end constants_pkg; 
    4/

Package created. 

SQL> select object_name, object_type, status 
    2 from user_objects 
    3 where status != 'VALID' 
    4 order by 1, 2 
    5/

OBJECT_NAME  OBJECT_TYPE  STATUS 
--------------- --------------- ------- 
PKG4   PACKAGE BODY INVALID 

SQL> 
SQL> set serveroutput on size unlimited 
SQL> exec pkg4.p7 
PKG4.P7::WHATEVER 

PL/SQL procedure successfully completed. 

SQL> select object_name, object_type, status 
    2 from user_objects 
    3 where status != 'VALID' 
    4 order by 1, 2 
    5/

no rows selected 

SQL> 

Alles, was gebaut mit CREATE OR REPLACE wird immer erstellt, es ist nur als ungültig markiert, wenn es Fehler gibt. Sobald wir es direkt oder indirekt ausführen, kompiliert die Datenbank es für uns. Also, Reihenfolge spielt keine Rolle. Wirklich nicht.

Wenn die Idee, einen Build mit ungültigen Objekten zu beenden, Sie betrifft - und ich habe etwas Mitgefühl damit, wird uns gesagt, nicht mit zerbrochenen Fenstern zu leben - können Sie das utlrp Skript verwenden oder in 11g the UTL_RECOMP package; Beide Ansätze erfordern einen SYSDBA-Account.

bearbeiten 2

Der Prozess um einen Build Tool basiert, die durch den Anbieter von gebaut wurde das Produkt, mit dem wir die Integration weshalb die einzigen Eingänge kann ich geben Der Build-Prozess sind eine Liste von Dateien in der Reihenfolge, die sie eingebaut sein müssen. Wenn es einen Compiler Fehler gibt, schlägt das Build-Tool fehl, wir haben manuell eine Anforderung für eine neue Build zu übermitteln.

Dies ist ein politisches Problem, kein technisches Problem. Was nicht heißt, dass politische Probleme nicht mit einer technischen Lösung gelöst werden können, nur dass die technische Lösung nicht das beste Werkzeug für den Job ist. Viel Glück.

+0

Ich fing an, dies von Hand zu tun, und erkannte, dass wir es weiterhin tun müssen, während das Projekt fortschreitet und neue Pakete hinzugefügt werden (und es wird neue Pakete geben, wahrscheinlich im späten Frühling - ich hätte gerne etwas automatisiertes vorher dann). – FrustratedWithFormsDesigner

+0

Auf jeden Fall den Build automatisieren. Aber wenn Sie jetzt ein Paket hinzufügen, müssen Sie es nur am Ende des Build-Skripts hinzufügen. Die Reihenfolge der Abhängigkeiten spielt bei Paketen keine Rolle. – APC

+0

Wenn sie den Code inkrementell erstellen würden, hätte ich recht. Es sieht so aus, als würden sie inkrementelle UND-Clean-Sweep-Builds durchführen, so dass die Build-Reihenfolge am wichtigsten ist, wenn sie die Umgebung bereinigen und neu aufbauen. – FrustratedWithFormsDesigner

0

Fügen Sie den folgenden Befehl an den Anfang des Skripts:

SET VERIFY OFF

dies Ihre Skripte erlauben ohne Validierung zu laufen und daher können in beliebiger Reihenfolge durchgeführt werden.

Sie können DBA_ERRORS später abfragen, um alle Fehler und Warnungen in Ihren Paketen, Sichten und Typen zu erhalten.

1

Eine kleine Sache, auf die man achten sollte, wenn man den Abhängigkeitsbaum durchläuft. Abhängigkeiten für nicht kompilierte Programme werden nicht angezeigt ...

SQL> drop package constants_pkg 
    2/

Package dropped. 

SQL> create or replace package body pkg4 is 
    2  procedure p7 is 
    3  begin 
    4   dbms_output.put_line('PKG4.P7::'||zzz_constants_pkg.whatever); 
    5  end p7; 
    6 end pkg4; 
    7/

Warning: Package Body created with compilation errors. 

SQL> show errors 
Errors for PACKAGE BODY PKG4: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
4/9  PL/SQL: Statement ignored 
4/43  PLS-00201: identifier 'ZZZ_CONSTANTS_PKG.WHATEVER' must be 
     declared 

SQL> 

So ist der Körper für PKG4 INVALID weil ZZZ_CONSTANTS_PKG existiert nicht.

SQL> create or replace package zzz_constants_pkg is 
    2  whatever constant varchar2(20) := 'WHATEVER'; 
    3 end zzz_constants_pkg; 
    4/

Package created. 

SQL> 

Aber der Körper für PKG4 ist noch INVALID so die folgende Abfrage nicht die Abhängigkeit zurückkehrt auf ZZZ_CONSTANTS_PKG ....

SQL> select name, type, referenced_name, referenced_type 
    2 from user_dependencies 
    3 where referenced_owner = user 
    4/

NAME   TYPE   REFERENCED_NAME REFERENCED_TYPE 
--------------- --------------- ----------------- --------------- 
PKG1   PACKAGE BODY PKG1    PACKAGE 
PKG1   PACKAGE BODY PKG2    PACKAGE 
PKG2   PACKAGE BODY PKG2    PACKAGE 
PKG2   PACKAGE BODY PKG3    PACKAGE 
PKG3   PACKAGE BODY PKG3    PACKAGE 
PKG3   PACKAGE BODY PKG1    PACKAGE 
PKG4   PACKAGE BODY PKG4    PACKAGE 

7 rows selected. 

SQL> 

Jetzt ist PKG4 lassen kompilieren und die Abhängigkeiten erneut abfragen ... .

SQL> alter package pkg4 compile body; 

Package body altered. 

SQL> select name, type, referenced_name, referenced_type 
    2 from user_dependencies 
    3 where referenced_owner = user 
    4/

NAME   TYPE   REFERENCED_NAME REFERENCED_TYPE 
--------------- --------------- ----------------- --------------- 
PKG1   PACKAGE BODY PKG1    PACKAGE 
PKG1   PACKAGE BODY PKG2    PACKAGE 
PKG2   PACKAGE BODY PKG2    PACKAGE 
PKG2   PACKAGE BODY PKG3    PACKAGE 
PKG3   PACKAGE BODY PKG3    PACKAGE 
PKG3   PACKAGE BODY PKG1    PACKAGE 
PKG4   PACKAGE BODY PKG4    PACKAGE 
PKG4   PACKAGE BODY ZZZ_CONSTANTS_PKG PACKAGE 

8 rows selected. 

SQL> 
0

Versuchen Sie dies stattdessen für 11.1 und höher. Führen Sie das Skript in beliebiger Reihenfolge aus. Am Ende geben Sie den folgenden Befehl ein: (Ändern Sie die Befehlsparameter an Ihre Bedürfnisse anzupassen)

-- Compile invalid objects 
EXEC DBMS_UTILITY.compile_schema(USER, FALSE); 

Mehr Details zu DBMS_UTILITY.compile_scema