使用外键和复合主键创建表

时间:2013-09-21 03:13:28

标签: sql foreign-keys primary-key

ProblemStatement: -

以下是我的表格 -

Employee (EmployeeId, EmployeeName, EmployeeCountry)
Training   (TrainingCode, TrainingName, TrainingType, TrainingTeacher)
Outcome  (EmployeeId, TrainingCode, Grade)

TrainingType字段将训练类型指定为,例如CASSANDRASQL等。

以下是我为上述用例创建的表格。我不知道如何创建第三个表 - 结果? EmployeeId, TrainingCode一起是主键吗?

CREATE TABLE employee
(
EmployeeId int,
EmployeeName varchar(255),
EmployeeCountry varchar(255),
PRIMARY KEY (EmployeeId)
);


CREATE TABLE Training
(
TrainingCode int,
TrainingName varchar(255),
TrainingType varchar(255),
TrainingTeacher varchar(255),
PRIMARY KEY (TrainingCode)
);

2 个答案:

答案 0 :(得分:5)

简洁地说,是的:Outcome表中EmployeeID和TrainingCode的组合是主键。这些列中的每一列也分别是其他两个表之一的外键。因此:

CREATE TABLE Outcome
(
    EmployeeId INT REFERENCES Employee,
    TrainingCode INT REFERENCES Training,
    Outcome VARCHAR(255),
    PRIMARY KEY(EmployeeID, TrainingCode)
);

您可能需要为您的特定DBMS提供其他一些词语,但要点应该清楚。


哪些员工参加过每个IT培训课程或每个商务培训课程?

正如聊天会话中所讨论的,您需要使用TDQD - 测试驱动的查询设计 - 一次建立一个答案。我将假设至少有一个IT培训课程和至少一个商务培训课程。如果您必须确保每个员工都被选中,例如,如果没有IT课程(例如,如果没有课程,每个员工都参加了所有可用的IT课程),那就非常棘手了。我也假设问题中的'或'是包容性OR,而不是排他性XOR。

  1. 查找IT培训课程的数量。

    SELECT COUNT(*) AS ITClassesAvailable
      FROM Training
     WHERE TrainingType = 'IT'
    
  2. 查找商务培训课程的数量。

    SELECT COUNT(*) AS BusinessClassesAvailable
      FROM Training
     WHERE TrainingType = 'Business'
    
  3. 查找至少参加过一次IT培训课程的每位员工所参加的IT培训课程的数量。

    SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
      FROM Outcome AS O
      JOIN Training AS T ON O.TrainingCode = T.TrainingCode
     WHERE T.TrainingType = 'IT'
    
  4. 查看至少参加过一次商务培训课程的每位员工所参加的商务培训课程的数量。

    SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
      FROM Outcome AS O
      JOIN Training AS T ON O.TrainingCode = T.TrainingCode
     WHERE T.TrainingType = 'Business'
    
  5. 找到参加过各种IT培训课程的员工。

    SELECT X.EmployeeID
      FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
              FROM Outcome AS O
              JOIN Training AS T ON O.TrainingCode = T.TrainingCode
             WHERE T.TrainingType = 'IT'
           ) AS X
      JOIN (SELECT COUNT(*) AS ITClassesAvailable
              FROM Training
             WHERE TrainingType = 'IT'
           ) AS Y
        ON X.NumberOfITCoursesTaken = Y.ITClassesAvailable
    
  6. 找到参加过各种商务培训课程的员工。

    SELECT X.EmployeeID
      FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
              FROM Outcome AS O
              JOIN Training AS T ON O.TrainingCode = T.TrainingCode
             WHERE T.TrainingType = 'Business'
           ) AS X
      JOIN (SELECT COUNT(*) AS BusinessClassesAvailable
              FROM Training
             WHERE TrainingType = 'Business'
           ) AS Y
        ON X.NumberOfBusinessCoursesTaken = Y.BusinessClassesAvailable
    
  7. 因此,参加所有IT课程或所有商务课程的员工名单是这两个查询的UNION,或者:

    SELECT X.EmployeeID
      FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
              FROM Outcome AS O
              JOIN Training AS T ON O.TrainingCode = T.TrainingCode
             WHERE T.TrainingType = 'IT'
           ) AS X
      JOIN (SELECT COUNT(*) AS ITClassesAvailable
              FROM Training
             WHERE TrainingType = 'IT'
           ) AS Y
        ON X.NumberOfITCoursesTaken = Y.ITClassesAvailable
    UNION
    SELECT X.EmployeeID
      FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
              FROM Outcome AS O
              JOIN Training AS T ON O.TrainingCode = T.TrainingCode
             WHERE T.TrainingType = 'Business'
           ) AS X
      JOIN (SELECT COUNT(*) AS BusinessClassesAvailable
              FROM Training
             WHERE TrainingType = 'Business'
           ) AS Y
        ON X.NumberOfBusinessCoursesTaken = Y.BusinessClassesAvailable
    

    同时参加了所有IT课程和所有商务课程的员工列表是两个查询的交集(使用INTERSECT代替UNION,或者使用UNION查询的两半连接)。 / p>

  8. 我不会一步一步地写出这样的查询;我通常不会第一次把它弄好。但是你可以看到我采取的步骤,并测试每个组件查询,你可以检查它们(a)在语法上是否正确,以及(b)对你的测试数据产生正确的答案,从那里你可以看到如何组合组件查询以进行更复杂的查询和最终查询。并且,如果有必要,可以随时进行更正。这是TDQD的好处。

答案 1 :(得分:1)

复合键可用于为结果表创建PK。您将需要在Employee和Training表上定义外键关系。

理想情况下,您将结果表上的结果字段设置为非null字段。

CREATE TABLE Outcome
(
   EmployeeId INT REFERENCES Employee,  -- fk to table employee
   TrainingCode INT REFERENCES Training, -- fk to table training
   Outcome VARCHAR(255) not null,
   PRIMARY KEY(EmployeeID, TrainingCode) -- compound PK
);