Как проверить, существует ли таблица в данной схеме



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 или более поздней версии.

623   3  

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'
   );

альтернатива: приведение к 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 вместо того, чтобы выдавать ошибку, если имя не нашел

возможно использовать 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

    Ничего не найдено.