代码之家  ›  专栏  ›  技术社区  ›  Danilo Bargen

MySQL:两个n:1关系,但不能同时使用

  •  5
  • Danilo Bargen  · 技术社区  · 14 年前

    我需要一个类似的数据模型: alt text

    我怎样才能解决这个问题?

    3 回复  |  直到 14 年前
        1
  •  8
  •   Bill Karwin    14 年前

    独占弧 在哪里 sets

    另一个解决方案是制作一个通用的“超级表”,这两个表 users schools

    create table set_owner
    
    create table users 
      PK is also FK --> set_owner
    
    create table schools
      PK is also FK --> set_owner
    
    create table sets 
      FK --> set_owner
    

    在OO建模中:

    interface SetOwner { ... }
    
    class User implements SetOwner { ... }
    
    class School implements SetOwner { ... }
    
    class Set {
      SetOwner owner;
    }
    

    所以SetOwner表同时包含userid和schoolid,对吗?这就意味着我将不被允许为一个用户和一个学校拥有相同的ID。我怎样才能执行这个?

    让SetOwners表生成id值。必须先插入setowner,然后才能插入用户或学校。所以把身份证放在用户和学校里 自动递增;只需使用setowner生成的值:

    INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
    INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');
    

    这样,学校和用户都不会使用给定的id值。

    Class Table Inheritance 图案。

    如果我想得到学校或用户的名字(不管是哪种类型的),我可以用一个查询来完成吗,还是需要两个查询(第一个查询类型,第二个查询名称)?

    你需要加入。如果您从给定的集合进行查询,并且您知道它属于某个用户(不是学校),那么您可以跳过加入集合所有者,直接加入用户。连接不一定非得按外键进行。

    SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...
    

    SELECT COALESCE(u.name, sc.name) AS name 
    FROM Sets s 
    LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id
    LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id 
    WHERE ...
    

    您知道SetOwner\u id必须与一个或另一个表、用户或学校匹配,但不能两者都匹配。

        2
  •  2
  •   geofflane    14 年前

    有一点需要注意:还不完全清楚数据模型中的集合是什么。

    我在质疑你的数据模型。

    只需为学校集和用户集创建单独的表。这将使反向查询更容易,因为您不必检查Sets表中的空关系,就可以知道它是真正的UserSet还是SchoolSet。

        3
  •  1
  •   OMG Ponies    14 年前

    您必须使用触发器来强制执行此业务规则,因为MySQL有但不强制执行CHECK约束(在任何引擎上)。