En el trabajo con PL/SQL es habitual encontrarse con distintos objetos de base de datos que han quedado en estado INVALID. Dependiendo de la cantidad de objetos y la complejidad del código PL/SQL utilizado la tarea de recompilar estos objetos puede volverse bastante pesada.
Oracle ofrece distintos medios para recompilar objetos:
- Identifying Invalid Objects
- The Manual Approach
- Custom Script
- DBMS_UTILITY.compile_schema
- UTL_RECOMP
- utlrp.sql and utlprp.sql
En el siguiente artículo detallan el uso y limitaciones de cada uno de ellos:
http://www.oracle-base.com/articles/misc/recompiling-invalid-schema-objects.php
Por mi parte, me decanto por el uso del paquete UTL_RECOMP. A continuación incluyo un script que nos permite recompilar todos los objetos de la base de datos marcados como no VALID:
set serveroutput on;
declare
v_num_invalid_objects number;
begin
dbms_output.put_line('Process start at '||to_char(sysdate, 'dd-Mon-yyyy hh24:mi:ss'));
select count(*) into v_num_invalid_objects from dba_objects where STATUS not like 'VALID';
if v_num_invalid_objects = 0 then
dbms_output.put_line('All objets are valid.');
else
dbms_output.put_line('There are '||trim(to_char(v_num_invalid_objects))||' invalid objects.');
for c_schemas in (select OWNER
from dba_objects
where STATUS not like 'VALID'
group by OWNER)
loop
begin
UTL_RECOMP.RECOMP_SERIAL(c_schemas.OWNER);
dbms_output.put_line('Schema compiled: '||c_schemas.OWNER);
exception
when others then
dbms_output.put_line('Error when recompile objets for schema '||c_schemas.OWNER||': '||sqlerrm);
end;
end loop;
select count(*) into v_num_invalid_objects from dba_objects where STATUS not like 'VALID';
if v_num_invalid_objects = 0 then
dbms_output.put_line('All invalid objects recompiled.');
else
dbms_output.put_line('**** After recompilation, there are '||trim(to_char(v_num_invalid_objects))||' invalid objects !!!!!');
for c_invobj in (select OWNER, OBJECT_NAME, OBJECT_TYPE, OBJECT_ID
from dba_objects
where STATUS not like 'VALID')
loop
dbms_output.put_line('* Invalid '||lpad(c_invobj.OBJECT_TYPE, 12, ' ')||': '||c_invobj.OWNER||'.'||c_invobj.OBJECT_NAME||' - id '||c_invobj.OBJECT_ID);
end loop;
end if;
end if;
dbms_output.put_line('Process finished at '||to_char(sysdate, 'dd-Mon-yyyy hh24:mi:ss'));
exception
when others then
dbms_output.put_line('General error: '||sqlerrm);
end;
Este proceso identifica todos los objetos en estado distintos de VALID que se encuentran en la base de datos y los recompila mediante el paquete UTL_RECOMP. Este paquete permite realizar recompilaciones de distintas formas. En el script que se incluye se utiliza la más sencilla de ellas. Pero retocando este script se puede incluir la posibilidad de recompilar objetos en paralelo o lanzar la recompilación a través de jobs.
Para más información sobre el paquete UTL_RECOMP (Oracle 10R2):
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_recomp.htm
