连接表的必要性是什么?

时间:2014-03-13 09:11:59

标签: sql join junction-table

我已经实现了以下存储关系拓扑的方法:

1.一般联合关系表:

  

表:关系

     

列:id parent_type parent_id parent_prop child_type child_id child_prop

大多数sql引擎通常不能执行哪些连接。

2.Relation特定联结表

  

表:Class2Student

     

列:id parent_id parent_prop child_id child_prop

哪些联接能够被执行。

3.在双向对象的text字段中查看相关对象的列表/字符串映射。

  

班级:班级

     

课程属性:id name students

     

表格列:id name students_keys

     

行:1"历史" [{类型:Basic_student,ID:1},{类型:Advanced_student,ID:3}]

要通过sql引擎启用连接,可以编写一个自定义模块,如果students_keys的内容只是[1,3],那么这个模块会变得更加容易,即关系是显式的{{1输入。

以下问题的背景如下:

我没有看到联结表的重点是什么。例如,我没有看到联结表的以下参数声称要解除的任何问题实际存在:

  • 无法在逻辑上正确保存双向关系(例如, 双向关系中没有数据孤立或任何数据孤立 与Student字段的关系,因为一个递归保存,一个可以强制执行 其他操作(删除,更新)非常容易)
  • 无法有效加入

我不会就您对最佳做法的个人意见或任何有关正常化的邪教言论征求意见。

明确的问题如下:

  1. 有哪些人希望通过查询拥有对象的keys字段来查询未提供的联结表?
  2. sql引擎提供的计算上下文中的逻辑实现问题是什么?联结表更可取?
  3. 关于keysjunction table字段的唯一实施差异如下:
  4. 在搜索具有以下性质的查询时,您需要使用自定义索引实现或其他一些合理的实现来匹配keys字段:

      

    class_dao.search({学生:advanced_student_3,名称:"历史"});

         

    搜索具有特定学生和姓名"历史"

    的班级

    而不是搜索联结表的索引列,然后选择适当的类。

    我一直无法确定答案为什么联结表在逻辑上更可取,因为任何原因。 我没有声称是这种情况,或者我是否有这样或那样的宗教偏好,因为我实现了多种实现方法。 我的问题是我不知道他们是什么。

1 个答案:

答案 0 :(得分:2)

我看到它的方式,你有几个实体

CREATE TABLE StudentType
(
    Id Int PRIMARY KEY,
    Name NVarChar(50) 
);

INSERT StudentType VALUES
(
    (1, 'Basic'),
    (2, 'Advanced'),
    (3, 'SomeOtherCategory')
);

CREATE TABLE Student
(
    Id Int PRIMARY KEY,
    Name NVarChar(200),
    OtherAttributeCommonToAllStudents Int,
    Type Int,
    CONSTRAINT FK_Student_StudentType
        FOREIGN KEY (Type) REFERENCES StudentType(Id)
)

CREATE TABLE StudentAdvanced
(
    Id Int PRIMARY KEY,
    AdvancedOnlyAttribute Int,
    CONSTRIANT FK_StudentAdvanced_Student
        FOREIGN KEY (Id) REFERENCES Student(Id)
)

CREATE TABLE StudentSomeOtherCategory
(
    Id Int PRIMARY KEY,
    SomeOtherCategoryOnlyAttribute Int,
    CONSTRIANT FK_StudentSomeOtherCategory_Student
        FOREIGN KEY (Id) REFERENCES Student(Id)
)
  1. 所有学生共有的任何属性都有Student表格中的列。
  2. 具有额外属性的学生类型将添加到StudentType表格。
  3. 每个额外的学生类型都会获得一个Student<TypeName>表来存储其特定属性。这些表与Student具有可选的一对一关系。
  4. 我认为你的&#34;稻草人&#34;联结表是EAV反模式的部分实现,这是唯一合理的时间,当您无法知道需要建模的属性时,即您的数据将完全是非结构化的。当这是一个真正的要求时,关系数据库开始变得不那么令人满意了。在这些情况下,考虑使用NOSQL /文档数据库替代。


    联结表在以下场景中很有用。

    假设我们将一个Class实体添加到模型中。

    CREATE TABLE Class
    (
        Id Int PRIMARY KEY,
        ...
    )
    

    我们希望在学生和班级之间存储多对多的关系,这是可以理解的。

    CREATE TABLE Registration
    (
        Id Int PRIMARY KEY,
        StudentId Int,
        ClassId Int,
        CONSTRAINT FK_Registration_Student
            FOREIGN KEY (StudentId) REFERENCES Student(Id),
        CONSTRAINT FK_Registration_Class
            FOREIGN KEY (ClassId) REFERENCES Class(Id)
    )
    

    这个实体是存储与学生注册课程特别相关的属性的正确位置,例如,可能是完成标志。其他数据自然与这个交汇点有关,也可能是特定类别的出勤记录或成绩历史。

    如果您不以这种方式与ClassStudent联系,您将如何选择课程中的所有学生以及学生阅读的所有课程。性能方面,这可以通过关键列上的索引轻松优化。


    当存在没有任何属性的多对多关系时,我在逻辑上同意,联结表不需要存在。但是,在关系数据库中,联结表仍然是一个有用的物理实现,也许就像这样,

    CREATE TABLE StudentClass
    (
        StudentId Int,
        ClassId Int,
        CONSTRAINT PK_StudentClass PRIMARY KEY (ClassId, StudentId),
        CONSTRAINT FK_Registration_Student
            FOREIGN KEY (StudentId) REFERENCES Student(Id),
        CONSTRAINT FK_Registration_Class
            FOREIGN KEY (ClassId) REFERENCES Class(Id)
    )
    

    这允许简单的查询,如

    // students in a class?
    SELECT StudentId
    FROM StudentClass
    WHERE ClassId = @classId
    
    // classes read by a student?
    SELECT ClassId
    FROM StudentClass
    WHERE StudentId = @studentId
    

    此外,这使得一种简单的方法可以部分或完全地从任一方面管理关系,这种关系对于关系数据库开发人员来说是熟悉的,并且可以被查询优化器所强调。