Depende do que você deseja testar exatamente .
Esquema de informação?
Para descobrir "se a tabela existe" ( não importa quem está perguntando ), a consulta do esquema de informações ( information_schema.tables
) está incorreta , estritamente falando, porque ( por documentação ):
Somente essas tabelas e visualizações são mostradas às quais o usuário atual tem acesso (por ser o proprietário ou ter algum privilégio).
A consulta fornecida pelo @kong pode retornar FALSE
, mas a tabela ainda pode existir. Responde à pergunta:
Como verificar se existe uma tabela (ou exibição) 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 é principalmente útil para se manter portátil nas principais versões e nos diferentes RDBMS. Mas a implementação é lenta, porque o Postgres precisa usar visualizações sofisticadas para estar em conformidade com o padrão ( information_schema.tables
é um exemplo bastante simples). E algumas informações (como OIDs) são perdidas na tradução dos catálogos do sistema - que na verdade carregam 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, por documentação empg_class
:
O catálogo pg_class
cataloga tabelas e quase todo o resto que possui colunas ou é semelhante a uma tabela. Isso inclui índices (mas veja também pg_index
), sequências , visualizações , visualizações materializadas , tipos compostos e tabelas TOAST ;
Para esta pergunta em particular, você também pode usar a visualizaçãopg_tables
do sistema . Um pouco mais simples e mais portátil nas principais versões do Postgres (o que dificilmente preocupa essa consulta básica):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Os identificadores devem ser exclusivos entre todos os objetos mencionados acima. Se você quiser perguntar:
Como verificar se um nome para uma tabela ou objeto semelhante em um determinado esquema é 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'
);
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 que ocupa esse nome) não existir.
Se você não qualificar o nome da tabela, uma conversão para o regclass
padrãosearch_path
e retorna o OID para a 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) fazem parte automaticamente do search_path
.
Você pode usar isso e capturar uma possível exceção em uma função. Exemplo:
Uma consulta como a anterior evita possíveis exceções e, portanto, é um pouco mais rápida.
Muito mais simples agora:
SELECT to_regclass('schema_name.table_name');
Igual ao elenco, mas retorna ...
... nulo em vez de gerar um erro se o nome não for encontrado
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
pg_tables
é realmente uma boa ideia para "Como verificar se existe uma tabela?" (Verificação de mesas única ., Não para outros fins, como explicado acima Além disso,pg_tables
é uma visão envolvendo várias mesas (pg_class
,pg_namespace
,pg_tablespace
), que é um pouco mais caro A razão mais importante:. Estou habituado a consultapg_class
diretamente e não fez pensarpg_tables
ao escrever esta resposta eu adicionei-o acima agora, obrigado..pg_my_temp_schema()
para obter o OID do esquema temporário real, se existir. (Mas as visualizações noinformation_schema
não incluem OIDs. Você poderiaSELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()
) Seu teste tem várias fraquezas. Um teste correto seriatable_schema LIKE 'pg\_temp\_%'
ou mais rigorosas:table_schema ~ '^pg_temp_\d+$'
.Talvez use information_schema :
fonte
Para PostgreSQL 9.3 ou menos ... Ou quem gosta de tudo normalizado para texto
Três sabores de minha biblioteca SwissKnife idade:
relname_exists(anyThing)
,relname_normalized(anyThing)
erelnamechecked_to_array(anyThing)
. Todas as verificações da tabela pg_catalog.pg_class e retornam tipos de dados universais padrão ( booleano , texto ou texto []).fonte