MySQL:我应该在哪里放置外键?

Posted

技术标签:

【中文标题】MySQL:我应该在哪里放置外键?【英文标题】:MySQL: Where should I place the foreign key? 【发布时间】:2015-03-12 09:19:27 【问题描述】:

我有一个疑问。请仔细阅读以下示例。

    有一种收入类型称为其他收入 每一项其他收入可能或可能不都需缴纳增值税。 一项其他收入只能有一项增值税(如果有的话)。

正如您在上述几点中看到的,其他收入增值税之间的关系是一对一/无

现在看下图。

我们希望 VAT 表包含 Other_Income 引用,因此 idVat 位于 Other_Income 表中。如果您想知道为什么会有单独的增值税表,这是因为许多其他类型的费用也需要缴纳增值税。

但是想象一下,由于某种原因,有人希望 Other_Income 表包含 VAT 参考。在这种情况下,如果您使用 mysql Work bench 或 GUI 工具构建图表,则关系行中的 1 将显示在 Other_Income 表的一侧,0..1 将出现在VAT表的旁边。

然而,不管它是什么,它都有一对一/无的联系。那么,Relationship 和外键的位置之间没有联系吗?换句话说,没有像You must put the foreign key to X table of the relationship. Other table is prohibited.这样的规则?

据我所知并知道没有这样的规则,您可以将外键放在关系中的任何表中,这只是您的偏好和决定让事情“工作”。不过我想澄清一下我的疑问。

更新

以上只是一个更有意义地解释问题的例子。因此,请不要让你的答案依赖于上面的例子。

【问题讨论】:

在物理模式的实践中,除非有特定的技术要求(例如,在某些数据库服务器中,您可能希望隔离一些大数据例如,将图像放入文件结构中的不同表和物理位置)。只需将增值税信息作为可选信息放入主表并使其可选 【参考方案1】:

当引用表中的列中的值始终出现在被引用表的列中并且被引用列在被引用表中是唯一的时,存在来自一个表列引用另一个表列的外键 (FK)。 (它被声明为 UNIQUE NOT NULL 或 PRIMARY KEY 。)此外,在 SQL 中,引用列可以为 NULL。

由于被引用的列在被引用的表中是唯一的,所以引用表中的行不是 NULL 并且与被引用表中的一行完全匹配,或者是 NULL。并且引用表中的许多行可能引用被引用表中的同一行。但是被引用表中的某些行可能不会被引用表中的任何行引用。因此,NOT NULL 引用行转到 1 个引用行,一个可为空的行转到 0 或 1 个引用行。一行被 0 个或多个引用行引用。所以外键意味着 0-or-many-to-(0-or-)1 的情况。

您的 1/2/3 只是说从 Other_Income 到 VAT 的 FK 可以为空。即 0 或多对 0 或 1。这并不能证明有一个 1 而不是很多,也不能证明有一个从 VAT 到 Other_Income 的 FK。即 1/2/3 表示“其他收入与增值税之间的关系是一对一/无”是不正确的。

如果碰巧还有其他限制,那么您还没有这么说。例如,在引用 Other_Income 的增值税中也有一个 FK。在这种特殊情况下,每个 Other_Income 都有自己的增值税(如果有的话)。 (如果增值税有的话,它也必须有自己的 Other_Income。)但是在这种情况下,如果增值税总是有匹配的 Other_Income,我们就有 Other_Income-VAT 1:0-or-1 并且如果增值税没有' 并不总是有 Other_Income,因此可以为空,然后我们有 Other_Income-VAT 0-or-1:0-or-1。 (我现在使用“:”,因为在两个方向都有一个“to”。)

只有在 1:1 的情况下,您才能选择在哪里放置 FK,而您却留下了一个 FK。具有讽刺意味的是,在 1:1 的情况下,您可以将所有信息放入一个没有 FK 的表中,这是对称和非冗余设计,而不是两个表。在 0-or-1:0-or-1 的情况下,如果我们想避免使用 NULL,那么我们将在任何一个表中都没有 FK,并添加第三个表,其中包含两列,每列一个 FK,每一个 PK,枚举成对价值观。

【讨论】:

我什么都不懂。我给出的例子只是一个解释“一般”问题的例子,所以请不要依赖它。 我给出了何时有 FK 的定义。 你只需要记住它并在你拥有它们时声明它们。我展示了一个 FK 是一个 0-or-something 到 (0-or-)1 的情况,引用的列在(0-or-)1 一侧和另一侧的引用“FK”列。这不是(0-或-)1到(0-或-)1的情况。这要么是两桌两 FK 的情况,要么是一桌无 FK 的情况。我只是以你的例子为例!【参考方案2】:

其他收入可以有增值税。因此,必须为该表指定一列 idVAT。对于每条记录,要么有一个条目,要么有一个 NULL。

所以你有一个 0-n:0-1 关系。每个增值税(“降低税率”、“正常税率”等)都可以分配给 n 个其他收入(n 为零或任何数字)。每个其他收入都可以有 0 或 1 个增值税。

为了不能在“其他收入”中输入不存在的 idVAT,您将其设为增值税表的外键。

如果您想要两个表之间真正的 1:0:1 关系,例如增值税表不包含增值税级别(“降低税率”、“正常税率”等),而是金额,那么事情会稍微复杂一些。

通常您不会制作这两张表,而只制作一张(增值税金额将是“其他收入”中的一个可为空的列)。如果您确实需要两个表,那么您应该为增值税表指定 idOther_Income,因为每个增值税条目都指向一个其他收入。所以这次反之亦然,但您仍然会使用外键来确保数据完整性。当然,这次是从增值税到其他收入。您还可以给 VAT.idOther_Income 一个唯一的约束条件,因此每个其他收入只能有一个增值税。

【讨论】:

【参考方案3】:

外键可以为空。在某些情况下,您只是不知道密钥的值是什么。 你可以看看这个link。

外键的关系和位置之间存在联系。如果您只是将外键的值放在未定义外键的表中,那将只是一个正常值,没有键提供的所有好处。

【讨论】:

【参考方案4】:

希望我能正确理解您的问题。 它接缝你有不同的费用表(如其他收入......)。费用表中的任何行都可能有增值税记录。 条件是:

如果没有费用,就不会产生增值税(如果我错了,请纠正我)。 费用需要跟踪其增值税(如果发生)。 增值税需要跟踪其费用(必须这样做)。 一项费用只能包含一个增值税。

我建议有一个名为Fee_Base(或简称为费用)的基表作为其他费用的基数。此基表将包含其他费用的共享属性,例如发生日期、金额等。 将 Fee_Base 外键在 VAT 中强制将满足 1,2 和 3 条件。 将 Fee_Base 外键分配为 唯一 将满足数字 4。

简单而言,Fee_Base foreign 是 VAT 表的主键。

【讨论】:

以上是关于MySQL:我应该在哪里放置外键?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL - 无法定义外键

MySQL外键(详解)

在mysql中链接外键时出错

MYSQL外键约束

在 LINQ 中访问外键在哪里?

mysql--外键(froeign key)-----------MySQL外键使用详解