Skip to content
MySQL

MySQL Error 1146

Table doesn't exist

Applies to: All MySQL versions (checked on MySQL 8.0.46)
Last technically reviewed 24 October 2026 on MySQL 8.0.46
The full message
ERROR 1146 (42S02): Table 'shop.customer' doesn't exist
Other forms of this message
PHP PDO
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'shop.customer' doesn't exist
DROP TABLE of a missing table (a separate error, 1051)
ERROR 1051 (42S02): Unknown table 'shop.order_items'
Error number
1146
SQLSTATE
42S02
Symbol
ER_NO_SUCH_TABLE
Product
MySQL Server
Versions
All MySQL versions (checked on MySQL 8.0.46)
Last reviewed
24 October 2026

What it means

Error 1146 means the database exists but has no table or view with the name the statement used.

The message always shows the full name MySQL looked for, database.table. That is the quickest check: is the database part the one you expected, and is the table name spelt exactly as it was created? For an unqualified name, the database part is the connection's default database, so 1146 can also mean the query ran against the wrong database. If the database itself is missing you get 1049 instead, and if no database is selected at all, 1046.

Letter case matters on most Linux servers. Table names map to files, and with lower_case_table_names = 0 (the default on Unix) Customers and customers are different tables. On Windows (default 1) and macOS (default 2) names are compared in lowercase, so code that works on a developer laptop can fail with 1146 after deployment to Linux. The setting can only be chosen when the server is initialised, so the lasting fix is consistent lowercase names in the code.

Common causes

  • A typo, or singular versus plural (customer for customers).
  • The connection's default database is not the one that holds the table, for example a staging database selected instead of production.
  • Letter case that differs from the table name on a server with lower_case_table_names = 0, typically after moving from Windows or macOS to Linux.
  • Migrations have not run (or ran in the wrong order), so the table is not created yet, or a restore was partial and skipped some tables.
  • A TEMPORARY table created in another connection. Temporary tables are visible only to the session that created them and are dropped when it ends, which matters with connection pools.

Diagnose it

Read-only These statements only read metadata (information_schema, performance_schema and SHOW statements) or your own data. They do not change data, privileges or configuration, so they are safe to run first.

Which tables exist in the current database?

SELECT DATABASE() AS current_db;

SELECT table_name, table_type
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY table_name;
What to look for

The default database and every table and view in it. Compare the exact spelling with the name in the error.

Search every database for a similar table name

SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_name LIKE '%customer%'
  AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY table_schema, table_name;
What to look for

Tables with a similar name in any database you can see. A match in another database means the query needs a qualifier (other_db.customers) or a different default database.

Is the server case-sensitive for table names?

SELECT @@lower_case_table_names AS lctn, @@version_compile_os AS os;
What to look for

0 means table names are case-sensitive, so the case in your SQL must match the case used in CREATE TABLE. 1 and 2 mean names are compared in lowercase.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Use the exact table name, qualified if needed

Client or network side

Copy the name from the table list. If the table lives in another database, qualify it or select that database for the connection.

SELECT id, name
FROM shop.customers
WHERE id = 1;

Make names lowercase and consistent before moving to Linux

Client or network side

Write table names in SQL exactly as they were created, and prefer all-lowercase names for new tables. Search the code for mixed-case table names before deploying from Windows or macOS to a Linux server.

SELECT id, name FROM customers;  -- not Customers

Create the missing table by running the migrations

Changes schema

When the code is right and the table is genuinely missing, run the migration or schema script that creates it, in order, rather than creating it by hand. After a partial restore, restore the missing tables from the backup.

Caution: Make sure you are connected to the intended database first. Creating an empty table to silence the error on the wrong database (or with a different design from the real one) hides missing data rather than fixing it.

CREATE TABLE IF NOT EXISTS order_items (
    order_id   INT NOT NULL,
    line_no    INT NOT NULL,
    product_id INT NOT NULL,
    qty        INT NOT NULL,
    PRIMARY KEY (order_id, line_no)
);

Use temporary tables only on the session that created them

Client or network side

Create and read a TEMPORARY table on the same connection, inside one unit of work. With a connection pool, the next query may run on another connection that cannot see it; use a regular table (or a derived table or CTE) when data must be shared between connections.

Examples

Singular instead of plural

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));

SELECT * FROM customer;
Result
ERROR 1146 (42S02): Table 'shop.customer' doesn't exist

Reproduced on MySQL 8.0.46, 24 October 2026.

A JOIN to a table that has not been created yet

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));
CREATE TABLE orders (id INT PRIMARY KEY, customer_id INT);

SELECT o.id, i.product_id
FROM orders AS o
JOIN order_items AS i ON i.order_id = o.id;
Result
ERROR 1146 (42S02): Table 'shop.order_items' doesn't exist

Reproduced on MySQL 8.0.46, 24 October 2026.

A migration that alters a table before creating it

-- 002_add_paid_flag.sql ran before 001_create_invoices.sql
ALTER TABLE invoices ADD COLUMN paid TINYINT NOT NULL DEFAULT 0;
Result
ERROR 1146 (42S02): Table 'shop.invoices' doesn't exist

Reproduced on MySQL 8.0.46, 24 October 2026.

A temporary table read from another connection

-- connection A
CREATE TEMPORARY TABLE tmp_totals (customer_id INT, total DECIMAL(10,2));

-- connection B (for example the next request from a pool)
SELECT * FROM tmp_totals;
Result
ERROR 1146 (42S02): Table 'shop.tmp_totals' doesn't exist

Reproduced on MySQL 8.0.46, 24 October 2026.

How to prevent it

Use lowercase table names, keep the database name in the connection settings, and run migrations in a fixed order from a tool that records which ones have run. Check that the schema is complete after every restore by comparing table counts with the source.

Test on the same operating system and lower_case_table_names setting as production, so case mistakes appear in development rather than after deployment.

Common questions

How do I fix MySQL error 1146 Table doesn't exist?

Read the database.table name in the message. Check the database part is the one you meant, then list the tables in it from information_schema.tables and compare the spelling and letter case. If the table really is missing, run the migration or restore that creates it.

Why does the table exist on Windows but not on Linux?

On Linux the default lower_case_table_names is 0, so table names are case-sensitive: Customers and customers are different. Windows compares names in lowercase. Use the exact case from CREATE TABLE, ideally all lowercase, in your SQL.

I just created a TEMPORARY table, so why is it missing?

A temporary table is only visible to the connection that created it and disappears when that connection closes. If your code uses a connection pool or reconnects, the next statement can run on a different connection.

What is the difference between 1146 and 1051?

Both mean the table was not found. 1146 is raised by statements that use a table, such as SELECT, INSERT and ALTER TABLE; DROP TABLE reports 1051 Unknown table instead. DROP TABLE IF EXISTS turns that into a note and carries on.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on MySQL 8.0.46. Message templates checked against the server's error catalogue (perror) for that version.

Still stuck on a MySQL error?

Browse the full MySQL error library, or get hands-on help from an experienced SQL professional.