Zapytanie o definicję zmaterializowanego widoku w Postgres

21

Zastanawiam się, jak zapytać o definicję zmaterializowanego widoku w Postgres. Dla porównania, to, co miałem nadzieję zrobić, jest bardzo podobne do tego, co możesz zrobić dla zwykłego widoku:

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

co daje następujące kolumny:

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

Czy jest to możliwe w przypadku zmaterializowanych widoków?

Z moich dotychczasowych badań wynika, że ​​zmaterializowane poglądy są celowo wyłączone z schematu_informacji, ponieważ

Information_schema może pokazywać tylko obiekty istniejące w standardzie SQL.

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

Ponieważ wydaje się, że są całkowicie wykluczeni ze schematu_informacyjnego, nie jestem pewien, jak to zrobić, ale chciałbym zrobić to podwójnie:

  1. Zapytanie, czy istnieje konkretny zmaterializowany widok. (Do tej pory jedynym sposobem, w jaki to zrobiłem, jest utworzenie widoku mat o tej samej nazwie i sprawdzenie, czy się wysadza).
  2. Następnie zapytaj o definicję zmaterializowanego widoku (podobnie jak w view_definitionkolumnie na information_schema.views).
Sean the Bean
źródło
Nieco związane pytanie dotyczące zapytania o unikalne ograniczenia w zmaterializowanych widokach: dba.stackexchange.com/questions/101899
Sean the Bean
Będziesz zainteresowany szybkim sposobem sprawdzenia istnienia: SELECT to_regclass('some_schema.some_mat_view')- jeśli zostanie znaleziony, nie musi to być jednak MV. Szczegóły: stackoverflow.com/questions/20582500/…
Erwin Brandstetter
Również: stackoverflow.com/questions/23092983/...
Erwin Brandstetter

Odpowiedzi:

13

Okazuje się, że to nie było tak skomplikowane, jak myślałem! (Przy odrobinie wiedzy na temat pg_catalog ...)

Część 1: Pytanie, czy istnieje widok zmaterializowany:

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';

Miło i łatwo.

Część 2: Zapytanie o definicję zmaterializowanego widoku:

Aby znaleźć zapytanie o definicję widoku maty, najpierw musiałem sprawdzić definicję information_schema.viewswidoku, uruchamiając:

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

Następnie skopiowałem zapytanie i zmieniłem c.relkind = 'v'::"char"na c.relkind = 'm'::"char", aby uzyskać widoki mat (zamiast zwykłych). Zobacz pełne zapytanie tutaj: http://pastebin.com/p60xwfes

W tym momencie można dość łatwo dodać AND c.relname = 'some_mat_view'i uruchomić, aby uzyskać definicję some_mat_view.

Ale nadal będziesz musiał to zrobić od nowa, kiedy będziesz chciał sprawdzić definicję widoku maty ...

Premia: Utwórz widok, aby to ułatwić

Zdecydowałem się utworzyć nowy widok, aby ułatwić wyszukiwanie definicji mat w przyszłości. Zasadniczo właśnie dodałem CREATE VIEW materialized_views ASna początku powyższego zapytania, aby utworzyć nowy widok, a teraz mogę go zapytać w następujący sposób:

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

Dużo lepiej!

Mogę również użyć tego widoku, aby łatwo zapytać, czy istnieje widok zmaterializowany, zmieniając *na count(*) > 0.

Oświadczenie : nie wiem, czy inne kolumny w wynikach zapytania są całkowicie poprawne, ponieważ zmaterializowane widoki zasadniczo różnią się od standardowych widoków ( myślę , że mają rację). Ale robi to przynajmniej kwerendy table_schema, table_namei view_definitionsłusznie.

Sean the Bean
źródło
0

Wadą pozostałych odpowiedzi jest to, że po prostu dostajesz definicję SQL, podczas gdy w większości przypadków interesują Cię rzeczywiste kolumny i możesz nimi manipulować jako tekst. Oto moja odpowiedź na podobne pytanie , które obejmuje nazwy kolumn i typy danych:

Nie mogę powiedzieć, że w pełni rozumiem podstawowy model danych, więc użyj mojego rozwiązania poniżej z odrobiną soli:

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

Musisz się zmienić 'your_schema'i 'your_materialized_view'.

André Christoffer Andersen
źródło