Depende de lo que quieras probar exactamente .
Esquema de información?
Para encontrar "si la tabla existe" ( no importa quién pregunte ), consultar el esquema de información ( information_schema.tables
) es incorrecto , estrictamente hablando, porque ( según la documentación ):
Solo se muestran aquellas tablas y vistas a las que el usuario actual tiene acceso (por ser el propietario o tener algún privilegio).
La consulta proporcionada por @kong puede regresar FALSE
, pero la tabla aún puede existir. Responde a la pregunta:
¿Cómo verificar si existe una tabla (o vista) y si el usuario actual tiene acceso a ella?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
El esquema de información es principalmente útil para mantenerse portátil en las principales versiones y en diferentes RDBMS. Pero la implementación es lenta, porque Postgres tiene que usar vistas sofisticadas para cumplir con el estándar ( information_schema.tables
es un ejemplo bastante simple). Y parte de la información (como los OID) se pierde en la traducción de los catálogos del sistema, que en realidad contienen toda la información.
Catálogos del sistema
Tu pregunta fue:
¿Cómo verificar si existe una tabla?
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
);
Utilice los catálogos del sistema pg_class
y pg_namespace
directamente, que también es considerablemente más rápido. Sin embargo, según la documentación sobrepg_class
:
El catálogo pg_class
cataloga tablas y casi todo lo demás que tiene columnas o es similar a una tabla. Esto incluye índices (pero vea también pg_index
), secuencias , vistas , vistas materializadas , tipos compuestos y tablas TOAST ;
Para esta pregunta en particular, también puede usar la vista del sistemapg_tables
. Un poco más simple y portátil en las principales versiones de Postgres (lo cual no es motivo de preocupación para esta consulta básica):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Los identificadores deben ser únicos entre todos los objetos mencionados anteriormente. Si quieres preguntar:
¿Cómo verificar si se toma el nombre de una tabla u objeto similar en un esquema dado?
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: emitir a regclass
SELECT 'schema_name.table_name'::regclass
Esto genera una excepción si la tabla (opcionalmente calificada por el esquema) (u otro objeto que ocupe ese nombre) no existe.
Si no califica el esquema del nombre de la tabla, una conversión a los regclass
valores predeterminados search_path
y devuelve el OID para la primera tabla encontrada, o una excepción si la tabla no se encuentra en ninguno de los esquemas enumerados. Tenga en cuenta que los esquemas del sistema pg_catalog
y pg_temp
(el esquema para objetos temporales de la sesión actual) son automáticamente parte de search_path
.
Puede usar eso y detectar una posible excepción en una función. Ejemplo:
Una consulta como la anterior evita posibles excepciones y, por lo tanto, es un poco más rápida.
Mucho más simple ahora:
SELECT to_regclass('schema_name.table_name');
Igual que el elenco, pero vuelve ...
... nulo en lugar de arrojar un error si no se encuentra el nombre
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
pg_tables
es realmente una buena idea para "¿Cómo verificar si existe una tabla?" (Comprobación de tablas sólo ., No para otros fines, como se explica más arriba también,pg_tables
es una vista que implica varias mesas (pg_class
,pg_namespace
,pg_tablespace
), que es un poco más caro La razón más importante:. Estoy acostumbrado a consultapg_class
directa y no lo hice piensepg_tables
al escribir esta respuesta. La agregué arriba ahora, gracias.pg_my_temp_schema()
para obtener el OID del esquema temporal real si existe. (Pero las vistas en elinformation_schema
no incluyen OID. PodríaSELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()
) Su prueba tiene varias debilidades. Una prueba correcta seríatable_schema LIKE 'pg\_temp\_%'
o más estrictas:table_schema ~ '^pg_temp_\d+$'
.Quizás use información_esquema :
fuente
Para PostgreSQL 9.3 o menos ... O a quién le gusta todo normalizado a texto
Tres sabores de mi biblioteca SwissKnife antigua:
relname_exists(anyThing)
,relname_normalized(anyThing)
yrelnamechecked_to_array(anyThing)
. Todas las comprobaciones de la tabla pg_catalog.pg_class y devuelve tipos de datos universales estándar ( booleano , texto o texto []).fuente