从视图创建视图后删除临时视图失败,改用临时视图能否解决?
嘿,让我来逐个帮你理清这两个PostgreSQL视图相关的问题:
问题1:能否从另一个视图创建视图,之后删除临时视图?
当然可以从一个视图(包括临时视图)创建新视图,但有个关键限制:如果你的目标常规视图是直接引用临时视图的,那你没法直接删除临时视图——因为PostgreSQL会严格维护对象间的依赖关系,常规视图需要依赖临时视图的存在才能正常工作。
不过如果你的需求是创建常规视图后就扔掉临时视图,那有个变通方法:不要让常规视图依赖临时视图,而是把临时视图的查询逻辑直接“复制”到常规视图的定义里(而不是简单写SELECT * FROM temp_view)。这样常规视图就和临时视图没有依赖关系了,你就能随意删除临时视图。
问题2:改用CREATE TEMP VIEW temp_view ...能否解决DROP VIEW失败的问题?
先解释下你之前失败的核心原因:你创建的main_viewYYYYMMDD是永久的常规视图,它的定义里直接引用了schema.temp_view(非临时视图),PostgreSQL会维护这种依赖关联,所以只要常规视图存在,你就删不掉被依赖的temp_view。
那改用临时视图能不能解决?分两种情况看:
- 如果你不需要手动删除临时视图:临时视图的生命周期只限于当前会话,会话结束后会自动消失。这种情况下你不用执行
DROP VIEW,它会自己清理,但要注意:你的main_viewYYYYMMDD会变成无效视图,因为它依赖的临时视图已经不存在了,后续查询这个常规视图会报错。 - 如果你想在同一个会话里手动删除临时视图:抱歉,还是会失败——因为常规视图依然依赖临时视图,PostgreSQL不会允许你删除被其他对象依赖的对象。
那真正的解决办法是什么?让常规视图彻底脱离对临时视图的依赖就行。你可以先获取临时视图的查询定义,再用这个定义直接创建常规视图,而不是引用临时视图。比如修改你的PL/pgSQL代码:
DO $$ DECLARE temp_view_query text; BEGIN -- 先拿到临时视图的查询语句 SELECT definition INTO temp_view_query FROM pg_views WHERE schemaname = 'pg_temp' AND viewname = 'temp_view'; -- 用临时视图的查询语句直接创建常规视图,而不是引用它 EXECUTE format( 'CREATE OR REPLACE VIEW schema.%I AS %s', getViewName(), temp_view_query ); -- 现在就能顺利删除临时视图了,因为常规视图已经不依赖它 DROP VIEW temp_view; END; $$ LANGUAGE plpgsql;
这样操作后,常规视图的定义是完全独立的,和临时视图没有任何依赖关联,你就能正常删除临时视图了。
内容的提问来源于stack exchange,提问作者ghostrider
相关产品推荐
相关产品推荐

