外键还是复合键?

时间:2016-05-26 07:29:25

标签: mysql sql entity-relationship foreign-key-relationship composite-primary-key

我刚刚开始应用我读到的关于表关系的所有内容,但我对如何在MANY-TO-MANY关系表上插入数据感到困惑,考虑到第三个表。

现在我有这些表格。

受试者

name
code PK
units
description

学年

schoolyearId PK
yearStart
yearEnd

schoolyearsubjects(很多很多桌子)

id PK
code FK
schoolyearId FK

但上述schoolyearsubjects表的问题在于,我不知道如何从GUI插入schoolyearId。在GUI屏幕截图中,只要单击"保存" 按钮,就会TRANSACTION包含 2 INSERT语句(到插入subject)和(插入schoolyearsubjects)将执行。如果我坚持上述内容,我将不得不插入schoolyearId。 schoolyearId肯定不会来自GUI。

enter image description here

我正在考虑将schoolyearsubjectsschoolyear的列更改为:

学年

--composite keys (yearStart, yearEnd)
yearStart (PK)
yearEnd (PK)

schoolyearsubjects(很多很多桌子)

id PK
code (FK)
yearStart (FK) --is this possible?
yearEnd (FK) --is this possible?

1。)解决方案是更改列并创建复合键,以便我可以只插入yearStartyearEnd值而不是schoolyearId吗?

2。)我的交汇点/链接表是否正确?

3.。)你能提出什么建议?

我很感激任何帮助。

感谢。

3 个答案:

答案 0 :(得分:1)

对我来说,schoolyear是一个时期,因此,没有必要在这里使用代理键。这总会让事情变得更加混乱,而且为它开发图形界面总是比较困难(我在谈论我们如何将时期建模为开发人员)。

如果你停下来思考,时期就会被视为独特的东西。你有一段时间等于另一个吗?停下来想一想。即使你有,这将发生在几年或不同的时间。所以我们已经有了一个schoolyear的主键。消除"校园PK"来自schoolyear。在这里使用复合键与yearStart和yearend。所以,你的校园实体(将来,表格)就像:

  • yearStart PK
  • yearEnd PK

在中间表中,您将有3个字段作为复合主键(也是外键!):

  • yearStart PK FK(来自schoolyear)
  • yearEnd PK FK(来自schoolyear)
  • 代码PK FK(来自主题)

这将允许一个时期只有一个主题。另一方面,如果您想要一个包含多个主题的句号,则必须在此处输入代理键。

现在,要绘制图形界面,您只需使用选择框(组合框)。在这种情况下,您将每个项目作为文本,例如"从X年到Y" (一段时间)。您的用户可以很好地理解并选择它。

注意:无论如何,您可能没有界面中记录的ID,但标识它的值。这是允许的,标识剩余的记录。

但是,如果您没有将某个时段作为独特的时段,那么" yearStart"和" yearEnd"是主题实体中的字段,并且没有schoolyear实体。说实话,实体" schoolyear"只有当你想将它的记录重用于与其他(s)表的其他记录的关系时才应该存在。我不是说这是或不是这样。小心一点。如果你这样做,你说每个时期只有一个主题(作为字段)。我不知道这是不是你想要的。我们必须始终记住塑造ER图中最重要的事情:

  • CONTEXT

检查您的背景。它有什么要求?如果您有任何疑问,请发表评论。如果你能在这里给我一些更多的背景信息,我可以帮助你。

答案 1 :(得分:0)

假设您的参数@code@yearStart@yearEnd包含来自用户界面的值:

INSERT INTO schoolyearsubjects ( code, yearStart, yearEnd )
SELECT @code, y.yearStart, y.yearEnd
  FROM schoolyear y
 WHERE @yearStart <= y.yearStart
       AND y.yearEnd <= @yearEnd;

...但我认为您的schoolyearsubjects存在设计缺陷,因为它允许重复,例如这样做:

INSERT INTO schoolyearsubjects VALUES ( 'code red', '2016', '2017' );
INSERT INTO schoolyearsubjects VALUES ( 'code red', '2016', '2017' );
INSERT INTO schoolyearsubjects VALUES ( 'code red', '2016', '2017' );

看起来会导致三个事实上重复的行。

答案 2 :(得分:0)

根据您当前的计划,您可以按照以下要求插入schoolyearId:


    INSERT INTO schoolyearsubjects (id, code, schoolyearId)
    VALUES ( ${id},
             ${code_from_GUI},
             ( SELECT schoolyearId
               FROM schoolyear
               WHERE yearStart=${start_from_GUI} AND yearEnd=${end_from_GUI})
           );

为此,需要在schoolyear表中对(yearStart,yearEnd)进行唯一约束。

至于你的其他问题:
1)您可以在schoolyear表中使用复合键,它将以任何方式工作 2)schoolyearsubjects是正确的,因为它允许编写连接查询。如果你摆脱了schoolyearId列,那么你可能不需要schoolyear表,因为你可能想要得到的所有数据都在schoolyearsubjects表中。
3)这article可能有助于确定使用哪种类型的密钥。