Удаление обычного или материализованного представления в Postgresql 9.3 одним запросом

У меня есть представление в моем PostgreSQL, которое может быть как обычным, так и материализованным, в зависимости от некоторых обстоятельств. Я пытаюсь написать запрос, который точно и без ошибок отбрасывает представление, независимо от того, какой тип у него есть на данный момент. Однако это не кажется легким. Когда я пытаюсь использовать следующий код, я получаю сообщение об ошибке:

DROP VIEW IF EXISTS {{ schema }}.{{ viewName }};
DROP MATERIALIZED VIEW IF EXISTS {{ schema }}.{{ viewName }};

 

SQLSTATE[42809]: Wrong object type: 7 ERROR:  "{{ viewName }}" is not a view  
HINT:  Use DROP MATERIALIZED VIEW to remove a materialized view.    

Таким образом, похоже, что «ЕСЛИ СУЩЕСТВУЕТ» возвращает true в первой строке, когда представление материализуется, команда DROP запускается, но терпит неудачу, потому что тип представления неверен (это ненормально). Может ли кто-нибудь предложить универсальный обходной путь, который будет работать как для материализованного, так и для обычного просмотра?


person Alexander Kachkaev    schedule 22.10.2013    source источник


Ответы (2)


Нет. Во всяком случае, не легко... Как сообщает Postgres, это два разных зверя.

Я думаю, что причина, по которой существует, заключается в том, что все это находится в pg_class. Если вы создадите тестовую таблицу и попытаетесь запустить drop view if exists test, вы получите аналогичную ошибку.

Вы можете, как не очень хороший обходной путь, сгенерировать динамический оператор SQL в блоке DO после проверки типа объекта в pg_catalog.pg_class, чтобы определить точный тип того, с чем вы имеете дело (таблица, представление, представление мата , так далее.).

person Denis de Bernardy    schedule 22.10.2013

Вот функция PLSQL для удовлетворения ваших потребностей:


CREATE OR REPLACE FUNCTION drop_any_type_of_view_if_exists(IN _viewname text)
RETURNS VOID AS
$$  
BEGIN
    RAISE LOG 'Looking for (materialized) view named %', _viewname;
    IF EXISTS (SELECT matviewname from pg_matviews where schemaname = 'public' and matviewname = _viewname) THEN
        RAISE NOTICE 'DROP MATERIALIZED VIEW %', _viewname;
        EXECUTE 'DROP MATERIALIZED VIEW ' || quote_ident(_viewname); 
    ELSEIF EXISTS (SELECT viewname from pg_views where schemaname = 'public' and viewname = _viewname) THEN
        RAISE NOTICE 'DROP VIEW %', _viewname;
        EXECUTE 'DROP VIEW ' || quote_ident(_viewname);
    ELSE
        RAISE NOTICE 'NO VIEW % found', _viewname;
    END IF;
END;
$$ LANGUAGE plpgsql;

Вы также можете вызвать созданную функцию со следующим синтаксисом


SELECT drop_any_type_of_view_if_exists('v_my_view');

person Damien C    schedule 17.08.2020