Ответ 1
Это зависит от того, что вы хотите проверить точно.
Информационная схема?
Чтобы найти "существует ли таблица" (независимо от того, кто спрашивает), запрос информационной схемы (information_schema.tables
) строго , потому что (для документации):
Отображаются только те таблицы и представления, которые имеют текущий пользователь к (в качестве владельца или имеющего некоторую привилегию).
Запрос продемонстрированный @kong, может вернуть FALSE
, но таблица все еще может существовать. Он отвечает на вопрос:
Как проверить, существует ли таблица (или представление), и у текущего пользователя есть доступ к ней?
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Информационная схема в основном полезна, чтобы оставаться переносной в основных версиях и в разных РСУБД. Но реализация выполняется медленно, потому что Postgres должен использовать сложные представления для соответствия стандарту (information_schema.tables
- довольно простой пример). И некоторая информация (например, OID) теряется при переводе из системных каталогов, которые фактически несут всю информацию.
Системные каталоги
Ваш вопрос:
Как проверить, существует ли таблица?
SELECT EXISTS (
SELECT 1
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
AND c.relkind = 'r' -- only tables
);
Используйте системные каталоги pg_class
и pg_namespace
напрямую, что также значительно быстрее. Однако в документации по pg_class
:
Каталог
pg_class
каталогизирует таблицы и большинство всего остального, что имеет столбцов или аналогично таблице. Это включает индексы (но см. такжеpg_index
), последовательности, представления, материализованные представления, типы и таблицы TOAST;
Для этого конкретного вопроса вы также можете использовать системный вид pg_tables
. Немного проще и более портативно в основных версиях Postgres (что вряд ли вызывает озабоченность в отношении этого базового запроса):
SELECT EXISTS (
SELECT 1
FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Идентификаторы должны быть уникальными среди всех объектов, упомянутых выше. Если вы хотите спросить:
Как проверить, принято ли имя для таблицы или аналогичного объекта в данной схеме?
SELECT EXISTS (
SELECT 1
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
);
Альтернатива: добавлено к regclass
SELECT 'schema_name.table_name'::regclass
Это вызывает исключение, если таблица (необязательно схема) (или другой объект, занимающий это имя) не существует.
Если вы не присваиваете схеме имя таблицы, приведение в regclass
по умолчанию соответствует search_path
и возвращает OID для первой найденной таблицы - или исключение, если таблица не включена ни в одну из перечисленных схем. Обратите внимание, что системные схемы pg_catalog
и pg_temp
(схема для временных объектов текущего сеанса) автоматически входят в состав search_path
.
Вы можете использовать это и уловить возможное исключение в функции. Пример:
Запрос, подобный выше, позволяет избежать возможных исключений и, следовательно, немного быстрее.
to_regclass(rel_name)
в Postgres 9.4 +
Намного проще:
SELECT to_regclass('schema_name.table_name');
То же, что и приведение, , но возвращается...
... null, а не бросать ошибку, если имя не найдено