更改其他视图中使用的列的类型

Joe*_*Dyk 6 postgresql views

create table base (name character varying(255));                                                                                                                                                        
create view v1 as select *, now() from base;                                                        
create view v2 as select * from v1 where name = 'joe';
alter table base alter column name type text;                                                       
Run Code Online (Sandbox Code Playgroud)

给出了这个错误:

cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on view v1 depends on column "name"
Run Code Online (Sandbox Code Playgroud)

这有点烦人,因为现在我必须重新创建引用该base.name列的所有视图.当我有引用其他视图的视图时,这尤其令人讨厌.

我希望能够做的是:

select recreate_views('v1', 'v2', 'alter table base alter column name type text');
Run Code Online (Sandbox Code Playgroud)

并让函数获取v1和v2的视图定义,删除它们,运行指定的代码,然后重新创建v1和v2.如果我可以使用Ruby,我可能会使用函数/ block/lambda,就像

recreate_views 'v1', 'v2' do
  alter table base alter column name type text
end
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?那里有没有类似的工具吗?

dbe*_*hur 8

我认为这可以做你想要的,虽然我将视图列表移动到args的末尾以与VARIADIC语义兼容.

CREATE OR REPLACE FUNCTION recreate_views(run_me text, VARIADIC views text[])
  RETURNS void
AS  $$
DECLARE
  view_defs text[];
  i integer;
  def text;
BEGIN
  for i in array_lower(views,1) .. array_upper(views,1) loop
    select definition into def from pg_views where viewname = views[i];
    view_defs[i] := def;
    EXECUTE 'DROP VIEW ' || views[i];
  end loop;

  EXECUTE run_me;

  for i in reverse array_upper(views,1) .. array_lower(views,1) loop
    def = 'CREATE OR REPLACE VIEW ' || quote_ident( views[i] ) || ' AS ' || view_defs[i];
    EXECUTE def;
  end loop;

END
$$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)