Sửa lỗi PostgreSQL ERROR: relation "table_name" does not exist

beginner🐘 PostgreSQL2026-03-18| PostgreSQL 12+, Linux/macOS/Windows, psql CLI, pgAdmin, mọi PostgreSQL client

Error Message

ERROR: relation "table_name" does not exist
#postgresql#table#schema#relation

Lỗi này trông như thế nào

ERROR: relation "table_name" does not exist
LINE 1: SELECT * FROM table_name;
                      ^

Bạn chạy một câu query mà bạn biết rõ là đúng — vậy mà PostgreSQL lại báo bảng không tồn tại. Bạn thấy rõ ràng nó ngay trong pgAdmin. Có bốn nguyên nhân gây ra lỗi này trong hầu hết mọi trường hợp, và không cái nào có nghĩa là dữ liệu của bạn đã mất.

Nguyên nhân

PostgreSQL nhận được query nhưng không thể tìm thấy bảng bạn chỉ định. Bản thân bảng có thể vẫn còn nguyên vẹn. Vấn đề thường là một trong những nguyên nhân sau:

  • Bảng nằm ở một schema khác và search_path của bạn không bao gồm nó
  • Phân biệt hoa thường — bảng được tạo với tên có chữ hoa/thường trong dấu ngoặc kép như "Users"
  • Bạn đang kết nối vào sai database (thường gặp trong môi trường nhiều database)
  • Bảng thực sự không tồn tại — migration chưa chạy, hoặc đã chạy trên môi trường sai
  • Đây là bảng tạm từ session khác — bảng tạm chỉ tồn tại trong session tạo ra nó và không hiển thị ở nơi khác

Cách sửa từng bước

Bước 1: Kiểm tra xem bảng có thực sự tồn tại không

Trước tiên, hãy xác nhận bảng có thực sự tồn tại không:

-- Liệt kê tất cả bảng trong mọi schema
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_name = 'your_table_name';

Hoặc trong psql:

\dt *.*

Không có kết quả? Bảng không tồn tại. Kiểm tra lại file migration hoặc chạy lệnh CREATE TABLE thủ công.

Bước 2: Kiểm tra Schema và Search Path

Mặc định PostgreSQL tìm kiếm trong schema public. Nhiều môi trường production sử dụng schema tùy chỉnh — app, api, reporting — và nếu search_path không bao gồm chúng, mọi query trên các bảng đó sẽ thất bại với lỗi này.

-- Xem search path hiện tại
SHOW search_path;

-- Xem schema hiện tại đang dùng
SELECT current_schema();

Bảng nằm trong schema tên app? Có ba cách xử lý:

-- Cách A: Thêm prefix schema vào tên bảng
SELECT * FROM app.users;

-- Cách B: Thêm schema vào search path cho session hiện tại
SET search_path TO app, public;
SELECT * FROM users;

-- Cách C: Đặt cố định cho user hiện tại
ALTER ROLE your_user SET search_path TO app, public;

Bước 3: Kiểm tra vấn đề phân biệt hoa thường

Lỗi này rất dễ gặp. PostgreSQL tự động chuyển tất cả định danh không có dấu ngoặc kép về chữ thường — vì vậy Users, users, và USERS đều trỏ đến cùng một thứ. Ngoại lệ: bảng được tạo với dấu ngoặc kép.

-- Tạo bảng như thế này:
CREATE TABLE "Users" (id serial, name text);

-- Lệnh này THẤT BẠI (PostgreSQL tìm tên viết thường "users"):
SELECT * FROM users;

-- Lệnh này HOẠT ĐỘNG:
SELECT * FROM "Users";

Tìm tên chính xác đã lưu trong database:

SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public';

Nếu kết quả hiển thị tên có chữ hoa/thường, bạn phải dùng dấu ngoặc kép trong mọi query. Cách tốt hơn về lâu dài: luôn dùng chữ thường với dấu gạch dưới khi tạo bảng — user_accounts thay vì UserAccounts.

Bước 4: Đảm bảo bạn đang kết nối đúng Database

Mỗi database PostgreSQL hoàn toàn độc lập. Một bảng trong db_production không thể thấy từ kết nối đến db_staging — dù trên cùng một server. Đây là bẫy kinh điển trong Docker và CI pipeline khi DATABASE_URL âm thầm trỏ đến nơi không mong muốn.

-- Kiểm tra database hiện tại
SELECT current_database();

-- Trong psql, chuyển database (cần kết nối lại)
\c correct_database_name

Dùng connection string trong ứng dụng? Kiểm tra lại tên database trong file .env hoặc config.

Bước 5: Kiểm tra xem có phải View hoặc Sequence không

Lỗi tương tự cũng xảy ra khi trỏ đến view hoặc sequence không tồn tại. Tìm kiếm trên tất cả loại đối tượng cùng một lúc:

SELECT schemaname, tablename, 'table' AS type FROM pg_tables WHERE tablename = 'target_name'
UNION ALL
SELECT schemaname, viewname, 'view' FROM pg_views WHERE viewname = 'target_name'
UNION ALL
SELECT schemaname, sequencename, 'sequence' FROM pg_sequences WHERE sequencename = 'target_name';

Kiểm tra lại sau khi sửa

Kiểm tra nhanh sau khi thực hiện thay đổi:

-- Nên trả về dữ liệu hoặc tập rỗng — không phải lỗi
SELECT * FROM your_schema.your_table LIMIT 5;

-- Xác nhận đang dùng đúng schema và database
SELECT current_schema(), current_database();

Đã thay đổi search_path cho một role? Ngắt kết nối và kết nối lại để xác nhận thay đổi có hiệu lực.

Mẹo nhanh

  • Đặt tên bảng bằng chữ thường với dấu gạch dướiuser_orders thay vì "UserOrders". Giúp loại bỏ vĩnh viễn vấn đề phân biệt hoa thường.
  • Dùng schema prefix tường minh (schema.table) đáng tin cậy hơn search_path, đặc biệt trong code chạy trên nhiều môi trường.
  • Trước khi chạy migration, chạy SELECT current_database(), current_schema(); để xác nhận đang nhắm vào đúng nơi.
  • Trong Docker hoặc CI, DATABASE_URL trỏ sai database là nguyên nhân số 1 của lỗi này ngoài môi trường local.
  • Django và SQLAlchemy đều hỗ trợ cấu hình schema tường minh — kiểm tra Meta.db_table hoặc __table_args__ nếu query chạy được trong psql nhưng lại lỗi trong ứng dụng của bạn.

Related Error Notes