web-dev-qa-db-fra.com

Interroger la définition d'une vue matérialisée dans Postgres

Je me demande comment interroger la définition d'une vue matérialisée dans Postgres. Pour référence, ce que j'espérais faire est très similaire à ce que vous pouvez faire pour une vue régulière:

SELECT * FROM information_schema.views WHERE table_name = 'some_view';

qui vous donne les colonnes suivantes:

table_catalog
table_schema
table_name
view_definition
check_option
is_updatable
is_insertable_into
is_trigger_updatable
is_trigger_deletable
is_trigger_insertable_into

Est-ce possible pour les vues matérialisées?

D'après mes recherches jusqu'à présent, il apparaît que les vues matérialisées sont délibérément exclues du schéma d'information, car

Le schéma_information ne peut afficher que les objets qui existent dans la norme SQL.

( http://www.postgresql.org/message-id/[email protected] )

Puisqu'ils semblent être entièrement exclus du schéma_information, je ne sais pas trop comment procéder, mais ce que j'aimerais faire est double:

  1. Recherchez s'il existe une vue matérialisée particulière. (Jusqu'à présent, la seule façon de le faire est d'essayer de créer une vue de tapis avec le même nom et de voir si elle explose.)
  2. Ensuite, interrogez la définition de la vue matérialisée (similaire à la view_definition colonne sur information_schema.views).
21
Sean the Bean

Il s'avère que ce n'était pas aussi compliqué que je le pensais! (Avec juste un peu de connaissance de pg_catalog ...)

Partie 1: Recherchez s'il existe une vue matérialisée:

SELECT count(*) > 0
FROM pg_catalog.pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'm'
AND n.nspname = 'some_schema'
AND c.relname = 'some_mat_view';

Agréable et facile.

Partie 2: Recherchez la définition d'une vue matérialisée:

Afin de proposer une requête pour obtenir la définition de la vue du tapis, j'ai d'abord dû rechercher la définition de la vue information_schema.views En exécutant:

SELECT view_definition
FROM information_schema.views
WHERE table_schema = 'information_schema'
AND table_name = 'views';

Ensuite, j'ai copié la requête et changé c.relkind = 'v'::"char" En c.relkind = 'm'::"char" Afin d'obtenir des vues de tapis (au lieu de vues régulières). Voir la requête complète ici: http://Pastebin.com/p60xwfes

À ce stade, vous pouvez facilement ajouter AND c.relname = 'some_mat_view' Et l'exécuter pour obtenir la définition de some_mat_view.

Mais il vous faudra tout de même recommencer la prochaine fois que vous chercherez la définition d'une vue de tapis ...

Bonus: créez une vue pour vous faciliter la tâche

J'ai choisi de créer une nouvelle vue pour faciliter la recherche de définitions de vues de tapis à l'avenir. J'ai simplement ajouté CREATE VIEW materialized_views AS Au début de la requête liée ci-dessus pour créer la nouvelle vue, et maintenant je peux l'interroger comme ceci:

SELECT *
FROM materialized_views
WHERE table_schema = 'some_schema'
AND table_name = 'some_mat_view';

Bien mieux!

Je peux également utiliser cette vue pour demander facilement s'il existe une vue matérialisée en remplaçant * Par count(*) > 0.

Clause de non-responsabilité : Je ne le sais pas, les autres colonnes des résultats de la requête sont entièrement correctes, car les vues matérialisées sont fondamentalement différentes des vues standard (I pensez ils ont raison). Mais cela interroge au moins correctement table_schema, table_name Et view_definition.

13
Sean the Bean

On dirait que 9.3 et plus vous pouvez faire:

select * from pg_matviews;
select * from pg_matviews where matviewname = 'view_name';

Plus d'informations trouvées ici: https://stackoverflow.com/questions/29297296/postgres-see-query-used-to-create-materialized-view

30
Dustin

L'inconvénient des autres réponses ici est que vous obtenez simplement la définition SQL, alors que dans la plupart des cas, vous êtes intéressé par les colonnes réelles et que vous pouvez les manipuler sous forme de texte. Ce qui suit est ma réponse d'un question similaire , qui comprend les noms de colonne et les types de données:

Je ne peux pas dire que je comprends parfaitement le modèle de données sous-jacent, alors utilisez ma solution ci-dessous avec un grain de sel:

select 
    ns.nspname as schema_name, 
    cls.relname as table_name, 
    attr.attname as column_name,
    trim(leading '_' from tp.typname) as datatype
from pg_catalog.pg_attribute as attr
join pg_catalog.pg_class as cls on cls.oid = attr.attrelid
join pg_catalog.pg_namespace as ns on ns.oid = cls.relnamespace
join pg_catalog.pg_type as tp on tp.typelem = attr.atttypid
where 
    ns.nspname = 'your_schema' and
    cls.relname = 'your_materialized_view' and 
    not attr.attisdropped and 
    cast(tp.typanalyze as text) = 'array_typanalyze' and 
    attr.attnum > 0
order by 
    attr.attnum

Vous devez changer 'your_schema'et 'your_materialized_view'.