• 数据库中避免树形结构出现回环图


    Q:以最简单的表结构设计出符合需求的组织架构? 
    A:组织架构通常是树形结构,上级包含下级所有权限。因此表结构可以如下设计: 
                +----+------+--------+ 
                | ID | NAME | parent | 
                +----+------+--------+ 
                其中parent为外键列,引用指向当前表ID,同时约束CHECK(ID <> parent) 来确保数据的有效性。 

    Q:是否可以仅通过一条SQL获取指定ID的所有子集列表? 
    A:不能。一条SQL只能在数据库执行一次,SQL仅具备常规逻辑(与[and], 或[or, in, not in], 非[is null, is not null])能力不具备如循环、递归等能力,所以不能直接通过一条SQL语句获取到所有需要的数据;因此要获取子集列表只能通过程序控制; 

    Q:如何获取子集列表? 
    A:可以有两种选择: 
      1、使用数据库支持的存储过程(Procedure); 
      2、使用编程语言(如:Java,C#,PHP等,该文以Java为例)循环实现; 
      对比: 
       +----+--------+----------------+ 
       |    |    Procedure    | PL(Programming Languages) | 
       +----+--------+----------------+ 
       |    优点   | 减少SQL传输 | 语言性能更强,更容易控制   | 
       +----+--------+----------------+ 
       |    缺点   | 增加DB响应时间 |   层次深、节点多时,SQL发 | 
       |    |        |    送次数不确定      | 
       +----+--------+----------------+ 
       递归层次3层以下且分支在2条左右可以使用PL实现,在此作者推荐Procedure方式实现; 

    Q:如何避免在树架构中出现图架构(回环)? 
    A: 关于这个问题,作者和同事在初时也是头疼不已;如何规避树结构夹杂图结构主要由以下两方面入手: 
       第一、数据插入前,递归(循环) 验证目标节点(TN--Target Node)未出现在准父级( FTB--Father-To-Be)的父节点列表中;从 TN->FTB 是不好查询的,而反过来则要容易得多:FBT->TN; 
       第二、为防止DB(数据库) 被通过非法途径污染架构树,在获取子集时也需要做验证(FBT->TN); 
        *第三、设置插入触发器(IT--Insert Trigger),更新触发器(UT--Update Trigger),在触发器中验证 FBT->TN合法性; 
        第四、经研究讨论后,发现一种更有效的方式避免在树结构中出现图结构: 
            为树结构中的每个节点定义层级概念! 
                +----+------+--------+-------+ 
                | ID | NAME | parent | Level | 
                +----+------+--------+-------+ 
        | 1  | name1|  null  |  null | 
                +----+------+--------+-------+ 
        | 2  | name2|   1    |   2   | 
                +----+------+--------+-------+  
        | 3  | name3|   1    |   2   | 
                +----+------+--------+-------+  
        | 4  | name4|  null  |  null | 
                +----+------+--------+-------+  
        | 5  | name5|   3    |   3   | 
                +----+------+--------+-------+  
         需求:1、将ID(3)父节点修改为ID(2).          a:获取ID(2)层级值(L2) 
              b:获取ID(3)层级值(L3) 
              c:验证ID(3)与ID(2)层级关系,被移动节点不能高于目标节点(L3>L2)
              d:获取L3需被提升的层次:DV=L3-L2-1 (DV--Difference  Value) 

              e:修改以ID(3)为根的所有子节点(包括ID(3))层次都提升 
            2、将ID(4)父节点分配为ID(3). 
              a:获取ID(3) 层级值(L3) 
              b:将L4修改为L3+1后完成操作 
            3、将ID(5)父节点修改为ID(4). 
              a:获取ID(4)层级值L4 
              b:获取ID(5)层级值L5 
              c:ID(5)不是根节点(L5<>1),设置L4=L5-1 
              d:ID(5)是根节点,设置L4=1同时修改以ID(5)为根的所有子节点(包括ID(5))层次都降低1

  • 相关阅读:
    django url 使用总结
    Django rest framework(7)----分页
    Django rest framework(6)----序列化
    Django rest framework(5)----解析器
    Django rest framework源码分析(4)----版本
    Django rest framework源码分析(3)----节流
    Django rest framework(2)----权限
    仿苹果app下载动画-煎饼
    搭建Gitlab
    npm Error: Cannot find module 'proto-list'
  • 原文地址:https://www.cnblogs.com/xm1-ybtk/p/5111933.html
Copyright © 2020-2023  润新知