4

我在我的 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.    

因此,当视图物化时,第一行中的 'IF EXISTS' 结果似乎为真,DROP 命令启动,但由于视图类型错误(不正常)而失败。谁能提出一个通用的解决方法,既适用于物化视图又适用于普通视图?

4

2 回答 2

1

没有。无论如何,或者不容易……正如 Postgres 报道的那样,这两者是不同的动物。

我认为如果存在的原因是因为这一切都驻留在 pg_class 中。如果您创建一个测试表并尝试运行drop view if exists test,您将收到类似的错误。

作为一个不太好的解决方法,您可以在检查 pg_catalog.pg_class 中的实体类型以确定您正在处理的内容的精确类型(表、视图、垫视图)之后,在 DO 块中生成动态 SQL 语句, ETC。)。

于 2013-10-22T17:24:45.760 回答
0

这是一个满足您需求的 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');

于 2020-08-17T08:46:41.630 回答