Fix “Catalog Error: Table Does Not Exist” in SQL
No table by that name is visible to the query. A typo, a missing schema, or a table that's already gone.
- DuckDB
-
Catalog Error: Table with name order_item does not exist! Did you mean "order_items"? - PostgreSQL
-
relation "order_item" does not exist - MySQL
-
Table 'garden_shop.order_item' doesn't existError 1146. The name is prefixed with the database.
- SQL Server
-
Invalid object name 'order_item'. - Oracle
-
ORA-00942: table or view does not exist - SQLite
-
no such table: order_item
The symptom
The query names a table the database can't find. DuckDB checks every table
name before it reads a single row, so the query fails straight away, and the
message tells you which name it looked for. Most of the time it's a spelling
slip: Garden Shop's line items live in order_items, and the
bench below asks for order_item.
The fix
Use the name the table really has:
select o.order_id, sum(oi.quantity)::integer as items
from orders as o
join order_item as oi on oi.order_id = o.order_id
group by o.order_id
order by o.order_id
limit 5;
Running it raises
Table with name order_item does not exist.
select o.order_id, sum(oi.quantity)::integer as items
from orders as o
join order_items as oi on oi.order_id = o.order_id
group by o.order_id
order by o.order_id
limit 5; Read the suggestion, carefully
DuckDB adds its closest match: Did you mean "order_items"? When
the name is one letter off, that's the answer. When nothing is close, it
still suggests something, and the suggestion is noise:
select * from sales on Garden Shop gets
Did you mean "sqlite_master"?, one of DuckDB's internal catalog
views. A suggestion that looks unrelated means no table in the database is
close to the name you typed.
List the tables that do exist
Ask the database instead of guessing:
show tables; select table_schema, table_name
from information_schema.tables
where table_name ilike '%order%'
order by table_name;
On Garden Shop that finds order_items and orders,
both in the main schema. More ways to look around:
SHOW TABLES and DESCRIBE.
Other reasons the table isn't there
It's in a schema you didn't name, or that doesn't exist
A schema-qualified name has to match both parts. DuckDB says which part is missing:
select count(*)
from staging.orders;
That fails with
Table with name "staging.orders" does not exist because schema "staging"
does not exist.
If the schema does exist, check that the table was created inside it and not
in main. See schemas.
A CTE only lasts for one statement
A with query names a result for the statement it belongs to.
The next statement can't see it:
with recent_orders as (
select * from orders
where order_date >= date '2024-06-01'
)
select count(*) from recent_orders;
select count(*) from recent_orders;
The first count runs. The second fails with
Table with name recent_orders does not exist! Repeat the
with block, or save the result with
create or replace table if several queries need it.
A view's table was dropped
DuckDB lets you drop a table that a view reads from. The view stays, and fails only when you query it, naming the table you didn't type:
create or replace table order_snapshot as
select * from orders where status = 'shipped';
create or replace view shipped_orders as
select order_id, order_date from order_snapshot;
drop table order_snapshot;
select count(*) from shipped_orders;
The last line fails with
Table with name order_snapshot does not exist! When the missing
name isn't in your query, look for a view in between. PostgreSQL would have
refused the drop instead. See
views.
On SQLShed: the table belongs to another dataset, or you dropped it
The playground holds one practice dataset at a time. Switching from Garden
Shop to Movie Rentals drops Garden Shop's tables, so a query on
products that worked a minute ago fails. Switch back, or check
the playground's table list for what's loaded now. A table you dropped or
renamed yourself stays gone until you reload the page, which restores the
dataset.
A create temp table doesn't survive to your next Run either:
each Run gets a fresh connection, and temporary tables belong to the
connection that made them. Use create or replace table for
anything you want to query again.
DuckDB matches table names without regard to case, even in double quotes:
select count(*) from "Customers" returns Garden Shop's 20
customers. PostgreSQL treats a quoted name as exact, so the same query fails
there with relation "Customers" does not exist. Write table
names in lowercase and you never meet the difference.
Guard scripts that drop and create
In a script that runs more than once, if exists turns a missing
table into a no-op instead of an error:
drop view if exists shipped_orders;
drop table if exists order_snapshot; Lesson 18.5 · Write a rerunnable script builds a whole script this way.
A misspelled function gets the same treatment:
Catalog Error: Scalar Function with name lenght does not exist! Did you
mean "length"?
How other engines word it
| Engine | Message |
|---|---|
| DuckDB | Catalog Error: Table with name order_item does not exist! Did you mean "order_items"? |
| PostgreSQL | relation "order_item" does not exist |
| MySQL | Table 'garden_shop.order_item' doesn't exist Error 1146. The name is prefixed with the database. |
| SQL Server | Invalid object name 'order_item'. |
| Oracle | ORA-00942: table or view does not exist |
| SQLite | no such table: order_item |
Related errors
- Fix “Referenced Column Not Found” in SQL
No table in the FROM clause has a column by that name. Usually a typo or a table you did not join.
- Fix “Is of Type View, Trying to Drop Type Table” in SQL
DROP TABLE will not remove a view, and IF EXISTS does not rescue it. Drop the type you made.
- Fix “Syntax Error at or Near” in SQL
The parser stopped at the first word it could not use. The quoted token is where it gave up, not always where the mistake is.