在CASCADE之后为视图创建创建数据库视图依赖树

时间:2019-06-25 13:28:14

标签: python sql postgresql amazon-redshift database-administration

我在数据库中有一个视图,其中每个记录都有两列:源和从属。在source列中是数据库中表/视图的名称,它是在从属列中找到的视图名称的源。我想使用Python创建另一个表,当使用CASCADE删除其源表时,该表可用于重新创建视图。

我知道我可以在SQL中使用CTE来实现每个“级别”的依赖关系。但是,我必须对每个级别进行硬编码,并且我需要动态级别的数量,以适应​​数据库中实现的级别数量。例如,如果视图“ b”依赖于表“ a”,则有两个级别,我可以为这两个级别编写代码。但是,如果创建了视图“ c”(取决于视图“ b”),那么现在有3个级别,我需要知道添加的级别并将其添加到我的代码中。

1 个答案:

答案 0 :(得分:0)

使用递归CTE,仅使用SQL即可获得所需的内容。为了进行可视化,我为您的示例添加了一个额外的层次。

--- set up 
create table view_dependencies (source_view text, depends_on_view text);

insert into view_dependencies( source_view, depends_on_view)
values ('b','a'), ('c','b'), ('d','c');

select * from view_dependencies;

-- show dependencies  
with RECURSIVE view_depends as (
   select source_view, depends_on_view, 1 lev
     from view_dependencies 
    where depends_on_view = 'a'
    UNION ALL
    select v.source_view, v.depends_on_view, lev+1
     from view_dependencies v
     join view_depends d on (v.depends_on_view = d.source_view)) 
SELECT * FROM view_depends;

-- extend the dependencies 
insert into view_dependencies( source_view, depends_on_view)
values ('g','d');

-- run the show dependencies query again.

好吧,因为您使用的工具不允许递归CTE,所以我首先会看到它提供了传递原始SQL语句(或也许更新工具)的能力。但是,假设这也不可用,您可以在其周围包装一个函数,如下所示。

create or replace function view_dependent_tree(base_view  text)
                   returns table (source_view text
                                 ,depends_on  text
                                 ,lev         integer
                                 ) 
 language plpgsql                                    
as $$
begin 
    for source_view 
       ,depends_on   
       ,lev    
    in  
        with RECURSIVE view_depends as (
             select d.source_view, d.depends_on_view, 1 lev
               from view_dependencies d
              where depends_on_view = base_view 
              UNION ALL
              select v.source_view, v.depends_on_view,d.lev+1
                from view_dependencies v
                join view_depends d on (v.depends_on_view = d.source_view)) 
        SELECT * FROM view_depends      
    loop
        return next;
    end loop; 
    return;
end; 
$$ ;   

select source_view, depends_on, lev from view_dependent_tree('a'); 

您是否已经提到无法使用递归CTE?好吧,这本来很好,但是这样做暗示了先验知识将是建议。我以为不是。不用担心。