Это зависит от того, что вы хотите , чтобы проверить точно .
Информационная схема?
Чтобы найти «существует ли таблица» ( независимо от того, кто спрашивает ), запрос информационной схемы ( information_schema.tables
) , строго говоря, некорректен , потому что ( согласно документации ):
Отображаются только те таблицы и представления, к которым у текущего пользователя есть доступ (будучи владельцем или обладающим некоторыми привилегиями).
Запрос, предоставленный @kong, может вернуться FALSE
, но таблица все еще может существовать. Это отвечает на вопрос:
Как проверить, существует ли таблица (или представление) и имеет ли текущий пользователь к ней доступ?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Информационная схема в основном полезна для переносимости между основными версиями и разными СУБД. Но реализация медленная, потому что Postgres должен использовать сложные представления, чтобы соответствовать стандарту ( information_schema.tables
это довольно простой пример). И некоторая информация (например, OID) теряется при переводе из системных каталогов - что на самом деле содержат всю информацию.
Системные каталоги
Ваш вопрос был:
Как проверить, существует ли таблица?
SELECT EXISTS (
SELECT 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 FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Идентификаторы должны быть уникальными среди всех объектов, упомянутых выше. Если вы хотите спросить:
Как проверить, берется ли имя для таблицы или подобного объекта в данной схеме?
SELECT EXISTS (
SELECT 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
.
Вы можете использовать это и поймать возможное исключение в функции. Пример:
Такой запрос позволяет избежать возможных исключений и поэтому работает немного быстрее.
Теперь намного проще:
SELECT to_regclass('schema_name.table_name');
То же, что и актерский состав, но он возвращается ...
... ноль, а не выдавать ошибку, если имя не найдено
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
pg_tables
на самом деле хорошая идея для "Как проверить, существует ли таблица?" (Проверка таблиц только ., А не для других целей, как объяснено выше Кроме того ,pg_tables
вид с участием нескольких таблиц (pg_class
,pg_namespace
,pg_tablespace
), который немного дороже Самая важная причина:. Я привык к запросуpg_class
непосредственно и не подумайте,pg_tables
когда пишете этот ответ. Я добавил его выше, спасибо.pg_my_temp_schema()
чтобы получить OID фактической временной схемы, если она существует. (Но в представленияхinformation_schema
нет OID. Вы могли быSELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()
) Ваш тест имеет несколько недостатков. Правильный тест будетtable_schema LIKE 'pg\_temp\_%'
более строгимtable_schema ~ '^pg_temp_\d+$'
.Возможно, используйте information_schema :
источник
Для PostgreSQL 9.3 или меньше ... Или кому нравится все нормализовано к тексту
Три ароматы моей старой библиотеки SwissKnife:
relname_exists(anyThing)
,relname_normalized(anyThing)
иrelnamechecked_to_array(anyThing)
. Все проверяет из таблицы pg_catalog.pg_class и возвращает стандартные универсальные типы данных ( логические , текстовые или текстовые []).источник