{
  "date": "2016-06-21T12:13:25",
  "slug": "ora-01775-looping-chain-of-synonyms",
  "link": "https://www.dbi-services.com/blog/ora-01775-looping-chain-of-synonyms/",
  "title": {
    "rendered": "ORA-01775: looping chain of synonyms"
  },
  "content": {
    "rendered": "<h2>By Franck Pachot</h2>\n<p>.<br />\nThis error message is misleading. You may encounter it when you expect ORA-00942: table or view does not exist. Let&#8217;s explain<br />\n<!--more--><br />\nI&#8217;m connected as SCOTT and create a PUBLIC SYNONYM for an object that do not exists:</p>\n<pre><code>\nSQL&gt; create public synonym MONEY for NOTHING;\nSynonym created.\n</code></pre>\n<p>No error message.<br />\nOnly when I read it I have an error message telling me that there are no table or view behind it:</p>\n<pre><code>\nSQL&gt; select * from NOTHING;\nselect * from NOTHING\n              *\nERROR at line 1:\nORA-00942: table or view does not exist\n</code></pre>\n<p>Let&#8217;s do the same but call it BONUS instead of MONEY:</p>\n<pre><code>\nSQL&gt; create public synonym BONUS for NOTHING;\nSynonym created.\n&nbsp;\nSQL&gt; select * from BONUS;\nno rows selected\n</code></pre>\n<p>No error here. Why? because I&#8217;ve a table that is called BONUS. So the name is resolved with the table and the synonym is not even tried.</p>\n<p>I&#8217;ll now drop that synonym and create it for the table BONUS. Same name for the public synonym and for the table.</p>\n<pre><code>\nSQL&gt; drop public synonym BONUS;\nSynonym dropped.\n&nbsp;\nSQL&gt; create public synonym BONUS for BONUS;\nSynonym created.\n</code></pre>\n<p>As user SCOTT, when I query BONUS the name is resolved as the table:</p>\n<pre><code>\nSQL&gt; show user\nUSER is \"SCOTT\"\nSQL&gt; select * from BONUS;\nno rows selected\n</code></pre>\n<p>As another user, when I query BONUS the name is resolved as the synonym, which finally reads SCOTT.BONUS:</p>\n<pre><code>\nSQL&gt; show user\nUSER is \"SCOTT\"\nSQL&gt; select * from BONUS;\nno rows selected\n</code></pre>\n<p>In 12c it is easy to see the final query:</p>\n<pre><code>\nSQL&gt; variable c clob\nSQL&gt; exec dbms_utility.expand_sql_text('select * from BONUS',:c);\nPL/SQL procedure successfully completed.\n&nbsp;\nSQL&gt; print c\n&nbsp;\nC\n----------------------------------------------------------------------------------------------------------\nSELECT \"A1\".\"ENAME\" \"ENAME\",\"A1\".\"JOB\" \"JOB\",\"A1\".\"SAL\" \"SAL\",\"A1\".\"COMM\" \"COMM\" FROM \"SCOTT\".\"BONUS\" \"A1\"\n</code></pre>\n<p>But now, what happens when we drop the table?</p>\n<pre><code>\nSQL&gt; drop table SCOTT.BONUS;\nTable dropped.\n</code></pre>\n<p>Do you expect a ORA-00942: table or view does not exist?</p>\n<pre><code>\nSQL&gt; select * from BONUS;\nselect * from BONUS\n              *\nERROR at line 1:\nORA-01775: looping chain of synonyms\n</code></pre>\n<p>Here is the &#8216;looping chain of synonyms&#8217;. I ask for BONUS. The name resolution first check for an object in my schema, but there are none:</p>\n<pre><code>\nSQL&gt; select object_type from user_objects where object_name='BONUS';\nno rows selected\n</code></pre>\n<p>Then it looks for public synonym and there is one:</p>\n<pre><code>\nSQL&gt; select object_type from all_objects where owner='PUBLIC' and object_name='BONUS';\n&nbsp;\nOBJECT_TYPE\n-----------------------\nSYNONYM\n</code></pre>\n<p>So we check what it is a synonym for:</p>\n<pre><code>\nSQL&gt; select table_owner,table_name from all_synonyms where owner='PUBLIC' and synonym_name='BONUS';\n&nbsp;\nTABLE_OWNER  TABLE_NAME\n------------ ------------\nSCOTT        BONUS\n</code></pre>\n<p>And there it is interesting. Besides the column names that includes &#8216;TABLE&#8217; a synonym can reference any object. So it&#8217;s not just replacing the synonym with &#8216;SCOTT.BONUS&#8217; which would raise an ORA-00942. It is doing name resolution of BONUS in the context of the user SCOTT. Something similar to:</p>\n<pre><code>\nSQL&gt; alter session set current_schema=SCOTT;\nSession altered.\nSQL&gt; select * from BONUS;\n</code></pre>\n<p>And then, what do you expect from that? There is no table named BONUS but there is a public synonym&#8230; and you&#8217;re back to the begining:</p>\n<pre><code>\nselect * from BONUS\n              *\nERROR at line 1:\nORA-01775: looping chain of synonyms\n</code></pre>\n<p>Most of the time, you don&#8217;t have synonyms that reference other synonyms, so you don&#8217;t really have a &#8216;chain&#8217; of synonyms. Except when there is only synonym in the namespace and it&#8217;s a self-reference loop. So if you see ORA-01775, check if the referenced object is not missing.</p>\n",
    "protected": false
  }
}
