Find Which Objects are INVALID in Oracle – and Why

March 26, 2019

in Data Dictionary, DBA, Exceptions, SQL, Views

INVALID Objects in Oracle

It is quite normal for Oracle database objects to become INVALID, especially when a dependency chain is broken. This article takes a closer look at:

  • typical reasons why Oracle objects become INVALID
  • how to identify INVALID objects in Oracle
  • how to convert INVALID objects to VALID

Why do Oracle objects become INVALID?

Oracle objects often become invalid during patching or upgrades because objects they depend on get dropped or altered in some way.

Let’s see this in action with a table having a dependent view and procedure.

The table:

SQL>  -- Table on which other objects depend
SQL>  create table temp_table
  2   ( id number);

Table created.

The dependent view and procedure:

SQL>  -- Dependent view
SQL>  create view temp_view
  2   as select * from temp_table;

View created.

SQL>  -- Dependent procedure
SQL>  create procedure temp_proc
  2   as
  3     l_id   number;
  4   begin
  5     select id into l_id
  6     from temp_table;
  7   end;
  8   /

Procedure created.

All the three objects – the table, the view and procedure — are valid at this time:

SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name like 'TEMP%';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_PROC          PROCEDURE      VALID
TEMP_TABLE         TABLE          VALID
TEMP_VIEW          VIEW           VALID

Now, we drop the table…

SQL> -- Drop the table; break the
SQL> -- dependency chain
SQL> drop table temp_table;

Table dropped.

…and check the status of the view and the procedure:

SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name like 'TEMP%';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_PROC          PROCEDURE      INVALID
TEMP_VIEW          VIEW           INVALID

Outcome: no more table — and both of the dependent objects have become invalid.

Another way objects become invalid is when errors occur at the time of creation or change. For example, a stored procedure gets created/replaced as valid if it compiles successfully, else it is invalid.

We can test this out with a procedure containing a coding error (a missing quote in dbms_output.put_line):

SQL> -- Procedure with compilation error
SQL> -- Will get created as INVALID; will not autocompile
SQL> create or replace procedure temp_proc_with_bug
  2  as
  3  begin
  4    dbms_output.put_line('Missing closing quote!);
  5  end;
  6  /

Warning: Procedure created with compilation errors.

When we check ALL_OBJECTS, we find that this procedure got created despite the error, but with status INVALID.

SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name = 'TEMP_PROC_WITH_BUG';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_PROC_WITH_BUG PROCEDURE      INVALID

How to identify INVALID objects in Oracle

The first step is to get the list of objects and their relevant details (type, last DDL time, etc.), with a filter for status INVALID. To get this information, query [DBA/ALL/USER]_OBJECTS depending on your privileges:

DBA_OBJECTS : All objects in the database
ALL_OBJECTS : All objects accessible to the user
USER_OBJECTS : All objects owned by the user

SQL> -- Check for invalid objects
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where status = 'INVALID';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEST_VIEW          VIEW           INVALID
TEMP_PROC          PROCEDURE      INVALID
TEMP_PROC_WITH_BUG PROCEDURE      INVALID

The next step is to find out *why* the object is invalid. To get this information, query [DBA/ALL/USER]_ERRORS depending on your privileges:

DBA_ERRORS : Current errors on all objects in the database
ALL_ERRORS : Current errors on all objects accessible to the user
USER_ERRORS : Current errors on all objects owned by the user

SQL> -- Check the error details
SQL> select name
  2       , type
  3       , line
  4       , position
  5       , text
  6  from all_errors
  7  where name like 'TEMP%';

NAME                 TYPE       LINE POSITION TEXT
-------------------- --------- ----- -------- -------------------------------------------
TEMP_PROC_WITH_BUG   PROCEDURE     4       24 PLS-00103: Encountered the symbol "Missing
                                              closing quote!);
                                              end;" when expecting one of the following:

                                                 ( ) - + case mod new not null <an identi
                                              fier>
                                                 <a double-quoted delimited-identifier> <
                                              a bind variable>
                                                 table continue avg count current exists
                                              max min prior sql
                                                 stddev sum variance execute multiset the
                                               both leading
                                                 trailing forall merge year month day hou
                                              r minute second
                                                 timezone_hour timezone_minute timezone_r
                                              egion timezone_abbr
                                                 time timestamp interval date
                                                 <a string literal with
 

Note that not all invalid objects will have errors listed for them in *_ERRORS; some will get an entry when we make an attempt to access them. You can see this in the results of the last two SQLs: though TEMP_VIEW and TEMP_PROC are listed as invalid in ALL_OBJECTS, they are absent from ALL_ERRORS as they have not been accessed yet.

Let’s try to access the invalid objects and check ALL_ERRORS again.

SQL> -- Query the INVALID view
SQL> select * from temp_view;
select * from temp_view
              *
ERROR at line 1:
ORA-04063: view "HR.TEMP_VIEW" has errors

SQL> -- Execute the INVALID package
SQL> exec temp_proc;
BEGIN temp_proc; END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object HR.TEMP_PROC is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

SQL> -- Check the error details
SQL> select name
  2       , type
  3       , line
  4       , position
  5       , text
  6  from all_errors
  7  where name like 'TEMP%';

NAME                 TYPE       LINE POSITION TEXT
-------------------- --------- ----- -------- -------------------------------------------
TEMP_PROC            PROCEDURE     5        3 PL/SQL: SQL Statement ignored
TEMP_PROC            PROCEDURE     6        8 PL/SQL: ORA-00942: table or view does not e
                                              xist

TEMP_PROC_WITH_BUG   PROCEDURE     4       24 PLS-00103: Encountered the symbol "Missing
                                              closing quote!);
                                              end;" when expecting one of the following:

                                                 ( ) - + case mod new not null <an identi
                                              fier>
                                                 <a double-quoted delimited-identifier> <
                                              a bind variable>
                                                 table continue avg count current exists
                                              max min prior sql
                                                 stddev sum variance execute multiset the
                                               both leading
                                                 trailing forall merge year month day hou
                                              r minute second
                                                 timezone_hour timezone_minute timezone_r
                                              egion timezone_abbr
                                                 time timestamp interval date
                                                 <a string literal with

TEMP_VIEW            VIEW          0        0 ORA-00942: table or view does not exist

The errors are now listed in ALL_ERRORS, since an attempt was made to query or access the invalid objects.

How to convert INVALID objects to VALID

Most of the time, you do not need to explicitly recompile objects. When there are no compilation failures, the object will turn from invalid to valid as soon as it is executed or accessed again.

To see how this works, let’s reinstate the missing object (table TEMP_TABLE) which had caused dependent objects (view TEMP_VIEW and procedure TEMP_PROC) to become invalid, and then check the status of dependent objects.

SQL> -- Reinstate the dropped table
SQL>  create table temp_table
  2   ( id number);

Table created.

SQL> -- BEFORE querying dependent view
SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name like 'TEMP_VIEW';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_VIEW          VIEW           INVALID

SQL> -- Query the dependent view
SQL> select * from temp_view;

no rows selected

SQL> -- AFTER querying dependent view
SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name like 'TEMP_VIEW';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_VIEW          VIEW           VALID

…which goes to show that the invalid object fixed itself on its own.

If you want to compile invalid objects in advance — perhaps to distinguish between those that would auto-fix themselves and those that wouldn’t – you can follow one of the these approaches.

1. ALTER…COMPILE per object

Compile objects selectively, one at a time, using the syntax:

ALTER [object_type] [object_name] COMPILE;

SQL> ALTER PROCEDURE temp_proc COMPILE;

Procedure altered.

If the compilation fails, use “sho err” on SQL*Plus to display errors.

SQL> ALTER PROCEDURE temp_proc_with_bug COMPILE;

Warning: Procedure altered with compilation errors.

SQL> sho err
Errors for PROCEDURE TEMP_PROC_WITH_BUG:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/24     PLS-00103: Encountered the symbol "Missing closing quote!);
         end;" when expecting one of the following:
         ( ) - + case mod new not null <an identifier>
         <a double-quoted delimited-identifier> <a bind variable>
         table continue avg count current exists max min prior sql
         stddev sum variance execute multiset the both leading
         trailing forall merge year month day hour minute second
         timezone_hour timezone_minute timezone_region timezone_abbr
         time timestamp interval date
         <a string literal with

2. DBMS_UTILITY.COMPILE_SCHEMA

Use DBMS_UTILITY.COMPILE_SCHEMA to compile all object types in the specified schema. This takes as input a “compile_all” option: if TRUE (the default), all objects in the schema are compiled, if FALSE only invalid objects are compiled.

exec dbms_utility.compile_schema(
    schema => '<schema_name>'
  , compile_all => FALSE -- Compile only INVALID objects
     );

Let’s see this action:

SQL> exec dbms_utility.compile_schema(schema => USER, compile_all => FALSE);

PL/SQL procedure successfully completed.

SQL> -- AFTER compile_schema
SQL> -- Check object validity
SQL> select object_name
  2       , object_type
  3       , status
  4  from all_objects
  5  where object_name like 'TEMP%';

OBJECT_NAME        OBJECT_TYPE    STATUS
------------------ -------------- -------
TEMP_PROC          PROCEDURE      VALID
TEMP_PROC_WITH_BUG PROCEDURE      INVALID
TEMP_TABLE         TABLE          VALID
TEMP_VIEW          VIEW           VALID

The objects that remain invalid after running DBMS_UTILITY.COMPILE_SCHEMA are those that need a review and fix of errors in *_ERRORS.

Summary

Oracle objects typically become invalid when a dependency chain is broken, or when they have errors at the time of compilation.

Invalid objects can be identified by querying *_OBJECTS with a filter on status = INVALID. Error details can be queried from *_ERRORS.

Invalid objects get automatically recompiled when they are accessed or executed. To compile them in advance, you can use ALTER…COMPILE per object, or DBMS_UTILITY.COMPILE_SCHEMA for all objects in the schema.

For Further Reading

Leave a Comment

Previous post:

Next post: