2012-03-14 57 views
5
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;              

使用的列的類型,給出了這樣的錯誤:更改其他視圖

cannot alter type of a column used by a view or rule 
DETAIL: rule _RETURN on view v1 depends on column "name" 

這有點討厭,因爲現在我必須重新創建所有引用的base.name列的意見。當我看到引用其他視圖的視圖時尤其令人討厭。

我很想能夠做的是一樣的東西:

select recreate_views('v1', 'v2', 'alter table base alter column name type text'); 

而且具有的功能得到v1和v2的視圖定義,刪除它們,運行指定的代碼,然後重新創建v1和V2。如果我可以使用紅寶石,我可能會使用函數/塊/ lambda,就像

recreate_views 'v1', 'v2' do 
    alter table base alter column name type text 
end 

是這樣的可能嗎?那裏的公用事業公司是否有類似的做法?

+0

'從pg_views選擇定義viewname表示= 'v1';'給你視圖定義 – dbenhur 2012-03-14 23:03:51

回答

7

我認爲這是做你想做的,雖然我把視圖列表移動到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; 
+1

爲了更加完整,可以找出如何查詢哪些視圖依賴於你正在修改的表,並使用該查詢而不是枚舉視圖名稱。需要了解pg_rewrite | pg_rule這樣做,我想。 – dbenhur 2012-03-14 23:52:24

+0

有趣,謝謝。我也有一些postgresql函數需要刪除和重新創建。我想我可以用類似的方法做到這一點。 – 2012-03-15 04:08:56

+0

我認爲視圖需要按照相反的順序創建(如果某些視圖依賴於其他視圖)。 – 2012-03-15 04:13:22

1

的改良效果會嘗試,如果它存在於所有下降鑑於前檢查,否則你會得到一個錯誤,所以這樣做:

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; 
    IF def IS NOT NULL THEN 
     EXECUTE 'DROP VIEW ' || schema_name || '.' || views[i]; 
    END IF; 
end loop; 

    EXECUTE run_me; 

for i in reverse array_upper(views,1) .. array_lower(views,1) loop 
    IF view_defs[i] IS NOT NULL THEN 
     def = 'CREATE OR REPLACE VIEW ' || schema_name || '.' || views[i] || ' AS ' || view_defs[i]; 
     EXECUTE def; 
    END IF; 
end loop;