Как проверить, существует ли таблица в данной схеме
Postgres 8.4 и выше база данных содержит общие таблицы в public схемы и конкретные таблицы компании в company схемы.company имена схем всегда начинаются с 'company' и закончить с номером компании.
Так что могут быть схемы:
public
company1
company2
company3
...
companynn
приложение всегда работает с одной компанией.
Элемент search_path указывается соответственно в строке подключения odbc или npgsql, например:
search_path='company3,public'
Как проверить, существует ли данная таблица в указанном companyn схемы?
select isSpecific('company3','tablenotincompany3schema')
должен возвратить false и
select isSpecific('company3','tableincompany3schema')
должен возвратить true.
в любом случае функция должна проверять только companyn схемы сдал, а не другие схемы.
если данная таблица существует в обоих public и переданная схема, функция должна возвращать true.
Он должен работать для Postgres 8.4 или более поздней версии.
3 ответов:
это зависит от того, что вы хотите, чтобы проверить ровно.
информация-схемы?
найти ", существует ли таблица" (независимо от того, кто спрашивает), запрос информационной схемы (
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это довольно простой пример). И некоторая информация (например, OIDs) теряется при переводе из системных каталогов - что на самом деле нести всей информации.система каталогов
Ваш вопрос:
Как проверить существует ли таблица?
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),последовательности,вид,материализованные представления,композитный типы и тосты таблицы;для этого конкретного вопроса, Вы также можете использовать посмотреть в системе
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' );альтернатива: приведение к
regclassSELECT '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 вместо того, чтобы выдавать ошибку, если имя не нашел
возможно использовать information_schema для:
SELECT EXISTS( SELECT * FROM information_schema.tables WHERE table_schema = 'company3' AND table_name = 'tableincompany3schema' );
для PostgreSQL 9.3 или меньше...Или кто любит все нормализовать к тексту
три аромата моей старой библиотеки SwissKnife:
relname_exists(anyThing),relname_normalized(anyThing)иrelnamechecked_to_array(anyThing). Все проверки из таблицы pg_catalog. pg_class и возвращает стандартные универсальные типы данных ( boolean,текст или текст[])./** * From my old SwissKnife Lib to your SwissKnife. License CC0. * Check and normalize to array the free-parameter relation-name. * Options: (name); (name,schema), ("schema.name"). Ignores schema2 in ("schema.name",schema2). */ CREATE FUNCTION relname_to_array(text,text default NULL) RETURNS text[] AS $f$ SELECT array[n.nspname::text, c.relname::text] FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace, regexp_split_to_array(,'\.') t(x) -- not work with quoted names WHERE CASE WHEN COALESCE(x[2],'')>'' THEN n.nspname = x[1] AND c.relname = x[2] WHEN IS NULL THEN n.nspname = 'public' AND c.relname = ELSE n.nspname = AND c.relname = END $f$ language SQL IMMUTABLE; CREATE FUNCTION relname_exists(text,text default NULL) RETURNS boolean AS $wrap$ SELECT EXISTS (SELECT relname_to_array(,)) $wrap$ language SQL IMMUTABLE; CREATE FUNCTION relname_normalized(text,text default NULL,boolean DEFAULT true) RETURNS text AS $wrap$ SELECT COALESCE(array_to_string(relname_to_array(,), '.'), CASE WHEN THEN '' ELSE NULL END) $wrap$ language SQL IMMUTABLE;
Comments