【问题标题】:How to remove a circular reference from relational database如何从关系数据库中删除循环引用
【发布时间】:2021-04-28 17:56:50
【问题描述】:

假设我正在构建一个包含群组和房间的聊天。我需要为它创建关系数据库方案。

  • 每个组可以有多个房间。
  • 而且每组总是只有 1 个主房间(这也是与其他房间相同的房间)
  • 房间已经预建(不管它是否是主房间)结构并且不能被复制。比如它的外键、描述、通知设置等。

因此,由于它是一对多关系,因此以下数据库模式可以代表此模型:

,-----------------.
|Group            |
|-----------------|
|*id: pk          |
|*name: string    |
|*main_room_id: fk|
`-----------------'
      ↑      ᗐ             
      ᗑ      ↓       
  ,-------------.  
  |Room         |  
  |-------------|  
  |*id:         |  
  |*name: string|
  |*notif: bool |    
  |*group_id: fk|  
  `-------------'  

但我想在这个方案中避免循环引用。我可以通过在表示这是主房间的房间中设置布尔字段来做到这一点:

 ,-------------.  
 |Group        |  
 |-------------|  
 |*id: pk      |  
 |*name: string|  
 `-------------'  
         ↑        
         ᗑ        
,----------------.
|Room            |
|----------------|
|*id:            |
|*name: string   |
|*notif: bool    |
|*group_id: fk   |
|*is_main: bool  |
`----------------'

但是在使用这个方案时数据库没有被规范化。主房间is_main布尔字段依赖于其他房间is_main字段。此外,应创建更复杂的约束以支持数据一致性。

什么是适合这个问题的数据库架构?

【问题讨论】:

    标签: database database-design schema relational-database


    【解决方案1】:

    我认为这不是多对一的关系。假设我理解正确,每个组可以与我们架构中的多个房间相关联,每个房间也可以与一个或多个组相关联,所以这意味着它是多对多的关系。

    例如,假设您可以在架构中拥有这些关联:

    Group     Room
    group_1   room_1
    group_1   room_2
    group_2   room_1
    group_2   room_2
    

    最好创建一个新实体来保存房间和组实体之间的关系。在这个新实体上,您可以有一个布尔字段来指示哪个关联是main

    【讨论】:

    • 不,一个房间可以属于一个组。换句话说,团体不能共享房间。房间也可以是无组的。尽管它是 M2O 或 M2M,但您的结构仍然是非规范化的(当您在 m2m 表上有布尔值时)
    【解决方案2】:
    -- Group GRP exists.
    --
    group {GRP}
       PK {GRP}
    
    -- Room ROM exists.
    --
    room {ROM}
      PK {ROM}
    
    • 每个房间属于最多一个组;
      每组可能拥有多个房间。
    -- Room ROM is owned by group GRP.
    --
    room_group {ROM, GRP}
            PK {ROM}
            SK {ROM, GRP}
    
    FK1 {ROM} REFERENCES room  {ROM}
    FK2 {GRP} REFERENCES group {GRP}
    
    • 每组最多有一个主房间;
      每个主房间都属于正好一个组。

    • 如果房间是小组的主要房间,
      那么该房间必须属于该组。

    -- Room ROM is main room for group GRP.
    --
    main_room {GRP, ROM}
           PK {GRP}
           AK {ROM}
    
            FK {ROM, GRP} REFERENCES
    room_group {ROM, GRP}
    

    注意事项:

    请注意,在模型中拥有主房间不是强制性的,请使用应用程序级别来强制执行。

    All attributes (columns) NOT NULL
    
    PK = Primary Key
    AK = Alternate Key   (Unique)
    SK = Proper Superkey (Unique)
    FK = Foreign Key
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-23
      • 2016-01-20
      • 2019-09-03
      • 1970-01-01
      • 2022-09-22
      相关资源
      最近更新 更多