PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como verificar se uma tabela existe em um determinado esquema


Depende do que você deseja testar exatamente .

Esquema de informações?


Para descobrir "se a tabela existe" (não importa quem está perguntando ), consultando o esquema de informações (information_schema.tables ) está incorreto , estritamente falando, porque (por documentação):

São mostradas apenas as tabelas e visualizações às quais o usuário atual tem acesso (por ser o proprietário ou ter algum privilégio).

A consulta fornecida por @kong pode retornar FALSE , mas a tabela ainda pode existir. Ele responde a pergunta:

Como verificar se uma tabela (ou visualização) existe e se o usuário atual tem acesso a ela?
SELECT EXISTS (
   SELECT FROM information_schema.tables 
   WHERE  table_schema = 'schema_name'
   AND    table_name   = 'table_name'
   );

O esquema de informações é útil principalmente para permanecer portátil nas principais versões e em diferentes RDBMS. Mas a implementação é lenta, porque o Postgres precisa usar visualizações sofisticadas para cumprir o padrão (information_schema.tables é um exemplo bastante simples). E algumas informações (como OIDs) se perdem na tradução dos catálogos do sistema - o que na verdade levar todas as informações.

Catálogos do sistema


Sua pergunta foi:

Como verificar se existe uma tabela?
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
   );

Use os catálogos do sistema pg_class e pg_namespace diretamente, o que também é consideravelmente mais rápido. No entanto, de acordo com a documentação em pg_class :

O catálogo pg_class cataloga tabelas e quase tudo que tem colunas ou é similar a uma tabela. Isso inclui índices (mas veja também pg_index ), sequências , visualizações , visualizações materializadas , tipos compostos e mesas TOAST;

Para esta pergunta em particular, você também pode usar a visualização do sistema pg_tables . Um pouco mais simples e mais portátil nas principais versões do Postgres (o que dificilmente é uma preocupação para esta consulta básica):
SELECT EXISTS (
   SELECT FROM pg_tables
   WHERE  schemaname = 'schema_name'
   AND    tablename  = 'table_name'
   );

Os identificadores devem ser únicos entre todos objetos mencionados acima. Se você quiser perguntar:

Como verificar se um nome para uma tabela ou objeto semelhante em um determinado esquema foi usado?
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'
   );
  • Resposta relacionada no dba.SE discutindo "Esquema de informações vs. catálogos do sistema"

Alternativa:transmitir para regclass

SELECT 'schema_name.table_name'::regclass

Isso gera uma exceção se a tabela (opcionalmente qualificada pelo esquema) (ou outro objeto ocupando esse nome) não existir.

Se você não qualificar o nome da tabela pelo esquema, uma conversão para regclass o padrão é o search_path e retorna o OID da primeira tabela encontrada - ou uma exceção se a tabela não estiver em nenhum dos esquemas listados. Observe que os esquemas do sistema pg_catalog e pg_temp (o esquema para objetos temporários da sessão atual) são automaticamente parte do search_path .

Você pode usar isso e capturar uma possível exceção em uma função. Exemplo:
  • Verifique se a sequência existe no Postgres (plpgsql)

Uma consulta como a acima evita possíveis exceções e, portanto, é um pouco mais rápida.

to_regclass(rel_name) no Postgres 9.4+


Muito mais simples agora:
SELECT to_regclass('schema_name.table_name');

Igual ao elenco, mas ele retorna...

... null em vez de lançar um erro se o nome não for encontrado