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

21

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_definitioncolonne sur information_schema.views).
Sean the Bean
la source
Question quelque peu liée à l'interrogation des contraintes uniques sur les vues matérialisées: dba.stackexchange.com/questions/101899
Sean the Bean
Vous serez intéressé par le moyen rapide de tester l'existence: SELECT to_regclass('some_schema.some_mat_view')- s'il est trouvé, il ne doit pas être un MV, cependant. Détails: stackoverflow.com/questions/20582500/…
Erwin Brandstetter
Aussi: stackoverflow.com/questions/23092983/…
Erwin Brandstetter

Réponses:

13

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 information_schema.viewsvue 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"pour c.relkind = 'm'::"char"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 l'ajouter AND c.relname = 'some_mat_view'et l'exécuter pour obtenir la définition de some_mat_view.

Mais il vous faudra encore 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 ASau début de la requête liée ci-dessus pour créer la nouvelle vue, et maintenant je peux l'interroger comme suit:

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 si une vue matérialisée existe en passant *à count(*) > 0.

Avertissement : je ne le sais pas, les autres colonnes dans les résultats de la requête sont entièrement correctes, car les vues matérialisées sont fondamentalement différentes des vues standard (je pense qu'elles ont raison). Mais cela ne demande au moins le table_schema, table_nameet view_definitioncorrectement.

Sean the Bean
la source
0

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. Voici ma réponse à une 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'.

André Christoffer Andersen
la source