ORA-01775 Zyklische Kette von Synonymen

Wer kennt das nicht?
Man setzt ein einfaches SQL Statement ab oder versucht ein Package zu kompilieren und bekommt folgende Fehlermeldung zurück:

ORA-01775: Zyklische Kette von Synonymen

Die Oracle Dokumentation sagt dazu folgendes:

ORA-01775 looping chain of synonyms

Cause: Through a series of CREATE synonym statements, a synonym was defined that referred to itself. For example, the following definitions are circular:

CREATE SYNONYM s1 for s2;
CREATE SYNONYM s2 for s3;
CREATE SYNONYM s3 for s1;

Action: Change one synonym definition so that it applies to a base table or view and retry the operation.

Soweit so gut. Es soll also Synonyme geben, die auf Synonyme verweisen, welche wiederum auf Synonyme verweisen, und wir kommen im Endeffekt nie auf eine Tabelle, View, Package, etc., um tatsächlich Daten abzufragen oder Programmcode auszuführen. Das kann einerseits passieren, weil Synonyme immer nur auf weitere Synonyme verweisen, oder andererseits die grundlegenden Objekte gar nicht existieren.

Nur wie finden wir die Problemstellen? Eine genaue Angabe welches Synonym das Problem verursacht, wird nicht angezeigt.

Folgendes Statement kann hier helfen:

Synonym Abfrage

-- Alle Synonyme die in der Verweiskette NUR Synonyme haben (also nirgendow hin führen)
-- Beinhaltet auch alle Synonyme die auf nicht existente Objekte verweisen
with base as
 (select t1.owner,
         t1.synonym_name,
         t1.table_owner,
         t1.table_name,
         t2.object_type
    from dba_synonyms t1, dba_objects t2
   where t1.table_owner = t2.OWNER
     and t1.table_name = t2.OBJECT_NAME),
conn as
 (select t1.owner,
         t1.synonym_name,
         t1.table_owner,
         t1.table_name,
         prior t1.owner prior_owner,
         prior t1.synonym_name prior_synonym,
         prior t1.table_owner prior_tab_owner,
         prior t1.table_name prior_tab_name,
         level lvl,
         connect_by_root object_type base,
         sys_connect_by_path(owner || '.' || synonym_name, '\') paths
    from base t1
  connect by nocycle prior owner = table_owner
         and prior synonym_name = table_name
   start with object_type <> 'SYNONYM')
select *
  from dba_synonyms
 where (owner, synonym_name) not in (select owner, synonym_name from conn)
 order by table_owner, table_name;

Alle Synonyme welche das vorige Skript zurück gibt, sollten mit Hilfe der Views DBA_SYNONYMS und DBA_OBJECTS entsprechend geprüft werden, ob sie „zyklisch“ sind oder auf nicht existente Objekte verweisen.