jueves, 20 de octubre de 2011

Sinónimos Huérfanos


Saludos
Los objetos tipos sinónimos (Públicos o privados) en la base de datos son alias a otros objetos de base de datos, por ejemplo si tenemos una tabla CLIENTES pero queremos que se la conozca como MIS_CLIENTES lo que se haría es crear el sinónimo para la tabla clientes de la siguiente tabla:
CREATE PUBLIC SYNONYM MIS_CLIENTES FOR CLIENTES;


Ya sabemos que los sinónimos son alias a los objetos de base de datos, pero ¿que pasa si el objeto al que hace referencia le cambiamos el nombre o eliminamos el objeto, el objeto Sinónimo también cambia de manera automática su referencia?
Pues la respuesta es no, lo que sucederá es que se dará el caso de "Sinónimos huérfanos" ya que el objeto sinónimos queda en el diccionario del SYS con la referencia al objeto anterior, por lo que para evitar esto es lo recomendable es que siempre que se borre o recree los sinónimos después de que se altere el nombre o borre algún objeto, siempre que se usen sinónimos para esos objetos.
En nuestro ejemplo del alias MIS_CLIENTES, si cambiamos el nombre a la tabla CLIENTES los pasos a seguir serian los siguientes:
--Cambiamos el nombre de la tabla
ALTER TABLE CLIENTES RENAME TO A_CLIENTES;
--Recreamos el sinónimo con el nuevo nombre de la tabla
CREATE OR REPLACE PUBLIC SYNONYM MIS_CLIENTES FOR A_CLIENTES;


Ya sabemos que es lo que debemos de hacer para no dejar sinónimos huérfanos, pero ¿Cómo sabemos que no existen más sinónimos huérfanos?
El siguiente script nos retornará la cantidad de sinónimos huérfanos:
--Cantidad de sinonimos huerfanos
select s.TABLE_OWNER, count(*)Cantidad from all_synonyms s
where not exists(select 1 from all_objects o where s.TABLE_OWNER=o.OWNER and s.TABLE_NAME=o.OBJECT_NAME )
and owner not in ('SYS','SYSTEM')
group by s.TABLE_OWNER;


El siguiente script te ayudará a eliminar los sinónimos huérfanos que existan:
begin
for v in (
select decode (owner,'PUBLIC','drop public synonym '||synonym_name,'drop synonym '||owner||'.'||synonym_name)||''vsql from all_synonyms s
where not exists(select 1 from all_objects o where s.TABLE_OWNER=o.OWNER and s.TABLE_NAME=o.OBJECT_NAME )
and owner not in ('SYS','SYSTEM')
)loop
begin
execute immediate v.vsql;
exception when others then
dbms_output.put_line(v.vsql||'-'||sqlerrm);
end;
end loop;
end;


Algo que también se debe de considerar es que se pueden crear sinónimos de objetos que no existen en la base de datos.