Cómo comprobar si existe una tabla en un esquema determinado

Resuelto Andrus asked hace 11 años • 3 respuestas

Las bases de datos Postgres 8.4 y posteriores contienen tablas comunes en publicel esquema y tablas específicas de la empresa en companyel esquema.
companyLos 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_pathespecifica 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 companynesquema 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 companynel esquema pasado, no otros esquemas.

Si una tabla determinada existe tanto en publicel esquema pasado como en el esquema pasado, la función debería devolver true.
Debería funcionar para Postgres 8.4 o posterior.

Andrus avatar Dec 14 '13 18:12 Andrus
Aceptado

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.tableses 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_classy pg_namespacedirectamente, lo que también es considerablemente más rápido. Sin embargo, según la documentación sobrepg_class :

El catálogo pg_classcataloga tablas y casi todo lo demás que tenga columnas o que sea similar a una tabla. Esto incluye índices (pero consulte también pg_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 regclasspredeterminado search_pathy 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_catalogy 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

Erwin Brandstetter avatar Jun 06 '2014 19:06 Erwin Brandstetter

Quizás utilice information_schema :

SELECT EXISTS(
    SELECT * 
    FROM information_schema.tables 
    WHERE 
      table_schema = 'company3' AND 
      table_name = 'tableincompany3schema'
);
kong avatar Dec 14 '2013 13:12 kong