Relation does not exist: распространённые ошибки при работе с PostgreSQL и PHP

Пример ошибки

SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "table_name" does not exist

Эта ошибка говорит о том, что PostgreSQL не может найти указанную таблицу (или представление) в текущей схеме базы данных.

Причины и решения

1. Таблицы действительно нет

Как может не быть таблицы, которая должна быть? Либо опечатка в названии таблицы (если при create table название заключить в кавычки, то название таблицы будет учитывать регистр), либо в приложении не прошли миграции (забыли запустить или во время их выполнения была ошибка)

Убедиться в наличии таблицы можно с помощью системного представления PostgreSQL:


SELECT * FROM information_schema.tables WHERE table_name = 'table_name';

SELECT to_regclass('table_name'); -- более простой запрос вернёт OID таблицы если она есть, null если её нет в текущей схеме

2. Неправильно указана схема

PostgreSQL, как и во многих других базах данных есть возможность использовать разные схемы. Это позволяет оптимизировать хранение и улучшить безопасность. Если явно не указать схему, то база будет искать таблицу в схеме по умолчанию (например public)

Схемы

SELECT * FROM table_name; -- если по умолчанию схема public, а таблица table_name находится в схеме private получим ошибку

-- Надо:
SELECT * FROM private.table_name;

SELECT to_regclass('private.table_name'); -- проверить есть ли таблица в указанной схеме

Интересный момент — схему в которой PostgreSQL ищет таблицу по умолчанию можно менять с помощью search_path.

Пример с search_path

-- У нас есть две таблицы pr_table_name в схеме private и pu_table_name в схеме public
SET search_path TO public;

SELECT * FROM pu_table_name; -- нет ошибки
SELECT * FROM pr_table_name; -- ошибка
SELECT * FROM private.pr_table_name; -- нет ошибки

SET search_path TO private;
SELECT * FROM pr_table_name; -- нет ошибки
SELECT * FROM pu_table_name; -- ошибка

SET search_path TO public, private;
SELECT * FROM pr_table_name; -- нет ошибки
SELECT * FROM pu_table_name; -- нет ошибки

3. Ошибка в подключении

При разработке можно легко забыть переключиться с одной базы данных на другую. И если ты подключен к не той базе или не к тому серверу там может не быть нужной таблицы

Профилактика ошибок

  1. Используйте CI/CD. Автоматический накат миграций при запуске деплоя поможет не забыть их накатывать самостоятельно
  2. Тестируйте перед выкатом обновлений. Заранее проверить выполняются ли миграции защитит от ошибок на продакшене
  3. Единый стандарт именования. Стандартизация названий позволит снизить путаницу. Лучше использовать только нижний регистр

Ошибка relation does not exist довольно простая и чаще всего встречается только во время разработки. Решить эту проблему можно примерно за 5 минут:

  1. Убедиться, что нет опечатки в названии таблицы
  2. Убедиться, что миграции были выполнены
  3. Проверить та ли схема указана
  4. Проверить к той ли базе подключены