ORA-00942 — 23 Procedures Fail After Synonym Drop
23 stored procedures failed simultaneously after DROP PUBLIC SYNONYM ORDERS.
- ORA-00942 means the database cannot resolve the object name at the current scope
- The object may exist but be inaccessible due to missing grants, wrong schema, or dropped synonyms
- Unlike ORA-06550 (compile-time), ORA-00942 is a runtime error that crashes the executing SQL statement
- It propagates as ORA-06512 through the PL/SQL call stack like any other unhandled exception
- Production insight: roughly 40% of ORA-00942 incidents trace back to missing or broken synonyms, not missing tables
- Biggest mistake: assuming the table was dropped when it actually exists in a different schema or the user simply lacks the grant to see it
ORA-00942 is Oracle telling you: "I cannot find what you are referring to." The table or view might physically exist on disk, but Oracle cannot see it from the current execution context. The three most common causes are: the object lives in a different schema and you forgot to qualify it, you lack SELECT privilege on the object, or a synonym pointing to the object is missing or broken. Fix the resolution path and the error disappears.
ORA-00942: table or view does not exist is raised at runtime when Oracle cannot resolve an object reference inside a SQL statement. The object name may be correct in the source code, but the database cannot find it in the current execution context.
The error is deceptively simple. The table exists. The name is spelled correctly. The code worked yesterday. Yet the statement fails. The cause is almost always a context change: a missing synonym, a revoked privilege, a schema migration, or a dropped public synonym after a cleanup script. Each root cause demands a different diagnostic path, and conflating them wastes hours.
ORA-00942 is one of the most common root causes of ORA-06512 in production PL/SQL systems. A procedure that references a table via an unqualified name or a synonym will compile without complaint but fail at runtime the moment the synonym is dropped or the privilege is revoked. The resulting error stack shows ORA-00942 as the originating error followed by one or more ORA-06512 entries tracing the call chain back to the top-level caller.
This guide walks through Oracle's name resolution order, the three major root cause categories — missing objects, missing synonyms, and missing privileges — and closes with automated prevention checks you can schedule today.
Name Resolution: How Oracle Finds Your Table
Oracle resolves object names through a deterministic sequence. Understanding this sequence is the single most important concept for diagnosing ORA-00942.
When Oracle encounters an unqualified table name — a name without a schema prefix — it searches in the following order: 1. It checks the current schema for a table or view with that name. 2. If no local object is found, it checks for a private synonym in the current schema. 3. If no private synonym is found, it checks for a public synonym. 4. If none of the above resolve, ORA-00942 is raised.
When Oracle encounters a qualified table name (schema.table), it bypasses synonym lookup entirely and goes directly to the specified schema. If the object does not exist in that schema, or the user lacks privilege to see it, ORA-00942 is raised.
The privilege check happens after name resolution succeeds. Oracle first resolves the name to a specific schema and object, then verifies that the executing user holds the required privilege (typically SELECT) on that resolved object. If the name resolves but the privilege is missing, Oracle still raises ORA-00942 — not ORA-01031 (insufficient privileges). This is by design: Oracle's security model prevents confirming the existence of objects to users who lack access. It is also the single most confusing aspect of this error, because the message says "does not exist" when the real problem is a missing grant.
In PL/SQL, the AUTHID clause determines whose privileges apply during execution. Definer's rights procedures (AUTHID DEFINER, the default) use the procedure owner's privileges and synonym context for name resolution. Invoker's rights procedures (AUTHID CURRENT_USER) use the calling user's privileges and synonym context. This distinction governs which synonyms are visible and which grants are effective at runtime.
- Unqualified name (ORDERS): current schema object → private synonym → public synonym → ORA-00942
- Qualified name (OWNER.ORDERS): direct lookup in specified schema → ORA-00942
- Privilege check happens AFTER resolution — a missing grant raises ORA-00942, not ORA-01031
- Definer's rights procedures (AUTHID DEFINER) use the owner's privileges and synonyms for resolution
- Invoker's rights procedures (AUTHID CURRENT_USER) use the caller's privileges and synonyms for resolution
Synonym Failures: The Invisible Dependency
Synonyms are the most common cause of ORA-00942 in multi-schema Oracle environments. They create implicit, invisible dependencies that span schemas — and dropping a synonym can break every unqualified reference that depends on it.
Public synonyms are the most dangerous because they are database-wide. Every schema in the instance can resolve an unqualified name through a public synonym. A single DROP PUBLIC SYNONYM command can break procedures, views, materialized view queries, and triggers across dozens of schemas simultaneously. The dependency is invisible because DBA_DEPENDENCIES does not reliably track public synonym resolution by PL/SQL objects — the dependency graph shows the synonym target, not the synonym itself.
Private synonyms are safer because they are schema-scoped. Dropping a private synonym only affects objects within that schema. But private synonyms still create implicit dependencies that are easy to overlook during schema reorganizations.
Broken synonyms — synonyms whose target object has been dropped or renamed — raise ORA-00980 (synonym translation is no longer valid) rather than ORA-00942. However, if the synonym itself is dropped, the resolution chain never reaches the synonym and ORA-00942 is raised instead. This distinction matters during diagnosis: ORA-00980 means a synonym exists but points to nothing; ORA-00942 means no synonym was found at all.
The diagnostic query for synonym-related ORA-00942 checks three locations: the current schema for private synonyms, PUBLIC for public synonyms, and the target schema for the actual object. If the object exists in another schema but no synonym points to it, the fix is either creating the synonym or qualifying the table name in the source code.
The permanent fix is to use fully qualified table names (schema.table) for all critical references. This eliminates synonym dependency entirely. The trade-off is code verbosity and coupling to the schema name, but in production the reliability gain is overwhelming.
- A public synonym is visible to every schema in the database — dropping it breaks every unqualified reference that depends on it
- DBA_DEPENDENCIES does not reliably track public synonym usage by PL/SQL objects — the dependency appears invisible in standard queries
- The only safe pre-drop check: search ALL_SOURCE across every application schema for the synonym name and review each hit
- Rule: never drop a public synonym without first searching ALL_SOURCE for references — the blast radius is the entire database
Privilege Failures: ORA-00942 Masking ORA-01031
Oracle raises ORA-00942 when the executing user lacks SELECT privilege on a table or view. The object exists, the name is correct, the synonym resolves — but the user cannot see the resolved object. This is the most confusing variant of ORA-00942 because the error message says "table or view does not exist" when the real problem is a missing grant.
The reason is Oracle's security model: confirming an object's existence to a user who lacks access is treated as an information disclosure vulnerability. If Oracle raised ORA-01031 (insufficient privileges), the user would learn that the object exists. Instead, Oracle returns the same generic ORA-00942 for both conditions, keeping the object's existence opaque.
The diagnostic path is straightforward once you know to check: first, verify the object exists by querying DBA_OBJECTS as a DBA user. If the object exists, query DBA_TAB_PRIVS and DBA_ROLE_PRIVS to check whether the executing user has the required privilege either directly or through a role.
For definer's rights PL/SQL (AUTHID DEFINER, the default), the procedure owner needs the direct grant — not the calling user. For invoker's rights PL/SQL (AUTHID CURRENT_USER), the calling user needs the grant. This distinction is critical because it determines which user's privileges Oracle evaluates at runtime.
Role-based grants introduce an additional subtlety. Roles are active during interactive SQL sessions and inside invoker's rights PL/SQL, but they are not active during definer's rights PL/SQL compilation or execution. If a table privilege is granted through a role, a definer's rights procedure cannot use it. The fix is a direct GRANT to the procedure owner — or switching the procedure to AUTHID CURRENT_USER.
This is one of the most frequently misdiagnosed ORA-00942 scenarios. Engineers see the error, confirm the table exists, confirm a grant exists through a role, and conclude that Oracle is buggy. The real problem is the definer's rights compilation model ignoring role-based grants.
- ORA-00942 for a missing object: the table was dropped or never created — verify with DBA_OBJECTS
- ORA-00942 for a missing privilege: the table exists but the user cannot see it — verify with DBA_TAB_PRIVS
- Oracle deliberately does not distinguish between the two because revealing object existence to unauthorized users is a security risk
- Diagnostic step one: query DBA_OBJECTS as DBA — if the object exists, the problem is privilege, not existence
- Definer's rights PL/SQL ignores role-based grants — only direct grants to the procedure owner are effective
Schema Qualification: The Permanent Fix
Fully qualified table names (schema.table) eliminate three classes of ORA-00942 failures at once: synonym drops, cross-schema resolution failures, and privilege confusion caused by synonym chains. The name resolves directly to the target schema without any synonym lookup step.
The trade-off is code verbosity and coupling to the schema name. Every table reference includes the schema prefix, which means renaming a schema or migrating to a different environment with different schema names requires updating every reference. In practice, schema renames are rare — they happen maybe once in the lifetime of a system — and the reliability gain far outweighs the coupling cost in production.
The migration pattern is incremental. You do not need to rewrite every SQL statement in a single sprint. Start by qualifying references to the most critical tables — the ones whose unavailability would cause the most business damage. Use static analysis queries against ALL_SOURCE to find unqualified references and prioritize by table criticality and call frequency.
For dynamic SQL, schema qualification must be enforced at the query construction level. Define a configuration package or a constant map that associates logical table names with fully qualified physical names. This centralizes the schema dependency into a single compilation unit and makes migration to a different schema a one-line configuration change rather than a grep-and-replace across hundreds of files.
Views deserve special attention. A view that references an unqualified table name inherits the synonym dependency of the schema where the view is compiled. If that synonym is dropped, the view becomes INVALID and any query against it raises ORA-04063 (which often cascades into ORA-00942 in the caller). Always use fully qualified names inside view definitions.
- Start with the most critical tables — qualify references to tables whose unavailability causes the most business impact
- Use the static analysis query (Pattern 5) to find all unqualified references — prioritize by table criticality and call frequency
- Centralize table name constants in a configuration package — makes schema migration a single recompile
- Always use qualified names inside view definitions — an unqualified reference makes the view dependent on a synonym
- Migrate incrementally: qualify one table at a time, test, deploy, repeat — do not attempt a full rewrite in a single change
Dynamic SQL and ORA-00942
Dynamic SQL introduces additional ORA-00942 risk because the object name is constructed at runtime as a string. The PL/SQL compiler cannot validate the reference at compile time — it is just a VARCHAR2 that may or may not resolve correctly when Oracle executes it.
The most common dynamic SQL ORA-00942 is caused by incorrect string concatenation. A missing space between FROM and the table name, an extra single quote, a wrong case when the table was created with double-quoted mixed-case identifiers — any of these produce a syntactically valid SQL string that references a non-existent object. The error message shows the constructed SQL, not the PL/SQL source line, which makes debugging painful if you did not log the string.
Another common cause is privilege context. EXECUTE IMMEDIATE uses the current session user's privileges, even when the enclosing procedure is compiled with AUTHID DEFINER. This is a subtle but critical distinction from static SQL. If the procedure owner has SELECT on a table but the calling user does not, static SQL in the same procedure succeeds while the dynamic SQL raises ORA-00942. The fix is either granting the privilege directly to the caller, using fully qualified names with a direct grant, or restructuring the dynamic SQL into a static cursor.
The third cause is synonym visibility. If the dynamic SQL uses an unqualified table name and the session user does not have a private synonym, and the public synonym was dropped, ORA-00942 is raised. The dynamic SQL is resolving names using the session user's synonym context, not the procedure owner's.
The non-negotiable practice for dynamic SQL is to log the fully constructed SQL string before execution. Without the actual string, ORA-00942 in dynamic SQL is a black box. DBMS_OUTPUT works for development; a dedicated logging table or the application's structured logging framework works for production.
- Dynamic SQL object names are strings — the compiler cannot validate them at compile time
- Privilege context differs from static SQL: EXECUTE IMMEDIATE uses the session user's privileges, even inside AUTHID DEFINER procedures
- String concatenation errors (missing spaces, wrong quoting, case sensitivity on double-quoted identifiers) cause ORA-00942 on valid objects
- Always log the constructed SQL before execution — without it, ORA-00942 in dynamic SQL is impossible to diagnose
- Use bind variables for all values — prevents SQL injection, eliminates quoting errors, and improves cursor sharing
Preventing ORA-00942: Automated Dependency Checks
ORA-00942 prevention requires automated checks that run at two points in the lifecycle: before deployments and on a recurring schedule. The checks verify that all referenced objects exist, are accessible, have valid synonyms, and have the required grants in place.
The pre-deployment check queries DBA_DEPENDENCIES for every object in the deployment changeset and verifies that every referenced object exists and has a VALID status. If any reference is broken — a missing table, an INVALID synonym, a dropped view — the deployment is blocked with a list of missing or invalid objects. This catches problems before they reach production.
The daily health check scans all application schemas for INVALID objects, broken synonyms (synonyms whose target has been dropped), and missing grants. It runs on a schedule and alerts the DBA team on any anomaly. The goal is to detect silent degradation — a revoked grant, a dropped synonym, a quietly invalidated package — before it triggers a runtime ORA-00942 during business hours.
The synonym impact check runs before any DROP SYNONYM command. It searches ALL_SOURCE for references to the synonym name across every application schema and reports the blast radius: how many objects in how many schemas reference the synonym. If the count is greater than zero, the drop is blocked until every reference is either updated to use a qualified name or a replacement synonym is created.
Combined, these three checks convert ORA-00942 from a runtime surprise into a pre-detected, preventable issue. The implementation cost is a handful of stored procedures and a scheduler job. The benefit is eliminating an entire class of production outages.
- Pre-deployment: run check_dependencies to verify all referenced objects exist and are VALID
- Daily at 06:00: run check_synonyms to detect broken synonyms before business hours
- Before DROP SYNONYM: run analyze_synonym_drop to measure blast radius and block if references exist
- Weekly: check for INVALID objects: SELECT owner, object_name, object_type FROM dba_objects WHERE status = 'INVALID' AND owner IN (application schemas)
- Use fully qualified names for the top 20 most critical tables — eliminates synonym dependency where it matters most
Public Synonym Dropped During Maintenance — 23 Procedures Failed Simultaneously
- Public synonyms are invisible dependencies — dropping one breaks every unqualified reference across every schema in the database
- Always query DBA_DEPENDENCIES and search ALL_SOURCE before dropping any database object — the dependency tree may span schemas you do not own or even know about
- Fully qualified table names eliminate synonym dependency entirely — schema.table resolves without synonym lookup
- Pre-deployment and pre-maintenance checks should verify that all referenced objects exist and remain accessible before any DDL is executed
Key takeaways
Common mistakes to avoid
6 patternsAssuming the table was dropped when ORA-00942 fires
Dropping public synonyms without checking references across all schemas
Using role-based grants for definer's rights PL/SQL and expecting them to work
Using unqualified table names in dynamic SQL without logging the constructed string
Not checking dependencies before deploying schema changes (table renames, schema reorganizations, object drops)
Confusing ORA-00942 with ORA-00980 and applying the wrong fix
Interview Questions on This Topic
What causes ORA-00942 and how do you diagnose it?
Frequently Asked Questions
That's PL/SQL. Mark it forged?
9 min read · try the examples if you haven't