Mysql 是否可以使用子表中引用的(通过外键)祖父母行中的字段';什么是复合外键? 完整问题:

Mysql 是否可以使用子表中引用的(通过外键)祖父母行中的字段';什么是复合外键? 完整问题:,mysql,composite-key,Mysql,Composite Key,从通过外键(引用祖父母主键)链接到其祖父母表中的行的子表中,是否可以使用子表复合外键中引用的祖父母行中的字段 我当前的数据库设计是有一个主父表,Projects项目有两个子表,职务和任务任务然后有一个子表子任务子任务然后有一个子表作业,这是一个x-ref表,将员工置于子任务。我遇到的问题是将职位分配给任务职务属于项目,因此任何给定项目下的作业只能引用共享项目的职务。我最近问过关于限制共享项目的人选择职位的问题。然而,从那时起,我发现复合外键是一个更干净的解决方案 简单数据库布局: 计划 职务

从通过外键(引用祖父母主键)链接到其祖父母表中的行的子表中,是否可以使用子表复合外键中引用的祖父母行中的字段

我当前的数据库设计是有一个主父表,Projects项目有两个子表,职务任务任务然后有一个子表子任务子任务然后有一个子表作业,这是一个x-ref表,将员工置于子任务。我遇到的问题是将职位分配给任务职务属于项目,因此任何给定项目下的作业只能引用共享项目的职务。我最近问过关于限制共享项目的人选择职位的问题。然而,从那时起,我发现复合外键是一个更干净的解决方案

简单数据库布局:
  • 计划
    • 职务
    • 任务
      • 子任务
        • 任务
我已经找到了如何创建复合键,但为此,我需要使用项目的主键作为复合外键的一部分

桌子:
  • 计划
    • 项目名称(主键)
    • ProjectID(唯一索引)
  • 职务
    • 职务
    • ProjectID(外键->Projects.ProjectID)(复合主键:JobTitle ProjectID)
    • JobTitleID(唯一索引)
  • 任务
    • 任务名
    • ProjectID(外键->Projects.ProjectID)(复合主键:TaskName ProjectID)
    • TaskID(唯一索引)
  • 子任务
    • 隐秘
    • TaskID(外键->Tasks.TaskID)(复合主键:子taskname TaskID)
    • 子任务(唯一索引)
  • 任务
    • EmployeeID(外键)
    • SubTaskID(外键->子任务.SubTaskID)(复合主键:EmployeeID SubTaskID)
    • JobTitleID(外键->JobTitleID)
    • AssignmentID(唯一索引)

为了将JobTitle分配给工作分配,我想使用工作分配的ProjectID(来自其父任务)及其选定的JobTitleID设置一个复合外键。唯一的问题是,我不知道如何获取两代人之外的projectd,以便在密钥中使用。通过在每个表中将projectd封装在复合键中,可以将其向下传递到每一代,但是考虑到复合键对性能的影响,复合键并不是随意丢弃的东西(更不用说向下传递值似乎有点草率)。是否有任何方法可以在不通过其他表的情况下访问键中使用的ProjectID?

正如您所说,您可以通过每个表向下传递ProjectID。我不认为这是草率的,它使您能够创建复合主键,以便在不同的项目中重用TaskID。一旦意识到这一点,我们就会发现在每个表中使用
ID
列的常见做法有点多余。相反,可以使用语义上有意义的数据作为键,这通常是我的首选(当然在空间方面成本更高,但索引对时间的影响相对较小):

由于MySQL不支持更强大的约束验证,我唯一能想到的另一个选项是在
Assignments
上定义
BEFORE INSERT
BEFORE UPDATE
触发器,这些触发器会引发错误以拒绝包含无效作业标题的数据。但是,您还需要在
作业标题
上创建触发器,以处理此类引用记录发生更改或被删除的情况;然后在所有其他可能导致链接中断的表上。丑陋的


因此,我更喜欢上面给出的第一种方法。

是的,如果我不能直接访问ProjectID,那么这肯定是最好的方法。我非常喜欢递归任务的想法(我最近才学会使用实际的标识索引作为PK而不是ID字段),但是任务布局是静态的(总是项目->任务->子任务,没有更多/更少)。谢谢你的帮助!
CREATE TABLE Projects (
  ProjectName VARCHAR(20) NOT NULL PRIMARY KEY
);

CREATE TABLE JobTitles (
  ProjectName VARCHAR(20) NOT NULL,
  JobTitle    VARCHAR(20) NOT NULL,
  PRIMARY KEY (ProjectName, JobTitle),
  FOREIGN KEY (ProjectName) REFERENCES Projects (ProjectName)
);

CREATE TABLE Tasks (
  ProjectName VARCHAR(20) NOT NULL,
  TaskName    VARCHAR(20) NOT NULL,
  ParentTask  VARCHAR(20),
  PRIMARY KEY (ProjectName, TaskName),
  FOREIGN KEY (ProjectName) REFERENCES Projects (ProjectName),
  FOREIGN KEY (ProjectName, ParentTask) REFERENCES Tasks (ProjectName, TaskName)
);

CREATE TABLE Assignments (
  ProjectName VARCHAR(20)  NOT NULL,
  TaskName    VARCHAR(20)  NOT NULL,
  JobTitle    VARCHAR(20)  NOT NULL,
  Email       VARCHAR(255) NOT NULL,
  PRIMARY KEY (ProjectName, TaskName, JobTitle),
  FOREIGN KEY (ProjectName) REFERENCES Projects (ProjectName),
  FOREIGN KEY (ProjectName, TaskName) REFERENCES Tasks (ProjectName, TaskName),
  FOREIGN KEY (ProjectName, JobTitle) REFERENCES JobTitles (ProjectName, JobTitle),
  FOREIGN KEY (Email) REFERENCES Employees (Email)
);