Cómo comprobar si existe una tabla en un esquema determinado
Las bases de datos Postgres 8.4 y posteriores contienen tablas comunes en public
el esquema y tablas específicas de la empresa en company
el esquema.
company
Los nombres de esquema siempre comienzan 'company'
y terminan con el número de empresa.
Entonces puede haber esquemas como:
public
company1
company2
company3
...
companynn
Una aplicación siempre funciona con una única empresa.
Se search_path
especifica en consecuencia en la cadena de conexión odbc o npgsql, como:
search_path='company3,public'
¿ Cómo comprobaría si una tabla determinada existe en un companyn
esquema específico?
p.ej:
select isSpecific('company3','tablenotincompany3schema')
debería regresar false
, y
select isSpecific('company3','tableincompany3schema')
debería regresar true
.
En cualquier caso, la función debe verificar solo companyn
el esquema pasado, no otros esquemas.
Si una tabla determinada existe tanto en public
el esquema pasado como en el esquema pasado, la función debería devolver true
.
Debería funcionar para Postgres 8.4 o posterior.
Depende de lo que quieras probar exactamente .
¿Esquema de información?
Para saber "si la tabla existe" ( sin importar 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 (ya sea por ser propietario o tener algún privilegio).
La consulta proporcionada por @kong puede devolver FALSE
, pero la tabla aún puede existir. Responde a la pregunta:
¿Cómo comprobar 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 seguir siendo portátil entre las versiones principales y entre 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 de sistemas
Tu pregunta fue:
¿Cómo comprobar 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, lo 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 tenga columnas o que sea similar a una tabla. Esto incluye índices (pero consulte tambiénpg_index
), secuencias , vistas , vistas materializadas , tipos compuestos y tablas TOAST ;
Para esta pregunta en particular también puedes utilizar la vista del sistemapg_tables
. Un poco más simple y más 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 comprobar si se toma el nombre de una tabla u objeto similar en un esquema determinado?
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'
);
- Respuesta relacionada en dba.SE que analiza "Esquema de información frente a catálogos de sistemas"
Alternativa: emitir aregclass
SELECT 'schema_name.table_name'::regclass;
Esto genera una excepción si la tabla (opcionalmente calificada por esquema) (u otro objeto que ocupe ese nombre) no existe.
Si no califica el esquema del nombre de la tabla, una conversión toma el valor regclass
predeterminado 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 los objetos temporales de la sesión actual) son automáticamente parte del archivo search_path
.
Puedes usar eso y detectar una posible excepción en una función. Ejemplo:
- Compruebe si la secuencia existe en Postgres (plpgsql)
Una consulta como la anterior evita posibles excepciones y, por lo tanto, es un poco más rápida.
Tenga en cuenta que aquí cada componente del nombre se trata como un identificador , a diferencia de las consultas anteriores donde los nombres se proporcionan como cadenas literales. Los identificadores se escriben en minúsculas a menos que estén entre comillas dobles. Si ha forzado identificadores que de otro modo serían ilegales entre comillas dobles, es necesario incluirlos. Como:
SELECT '"Dumb_SchName"."FoolishTbl"'::regclass;
Ver:
- ¿Los nombres de las columnas de PostgreSQL distinguen entre mayúsculas y minúsculas?
to_regclass(rel_name)
en Postgres 9.4+
Mucho más sencillo ahora:
SELECT to_regclass('schema_name.table_name');
Igual que el elenco, pero regresa...
... nulo en lugar de arrojar un error si no se encuentra el nombre
Quizás utilice information_schema :
SELECT EXISTS(
SELECT *
FROM information_schema.tables
WHERE
table_schema = 'company3' AND
table_name = 'tableincompany3schema'
);