【问题标题】:phpmyadmin: Foreign key not populating when data entered into primary keyphpmyadmin:将数据输入主键时未填充外键
【发布时间】:2019-03-03 14:21:31
【问题描述】:

我有一个非常简单的数据库,它有 2 个表。这是我的表的一个例子:

我已将代码列 ID 设置为主键... 并且访问代码coiumn id_fk 是外键。

每当我通过 phpmyadmin 向代码表添加数据时,access_codes 列 id_fk 不会给我提供与主键相同的数据。

我已经在 phpmyadmin 中建立了关系,因为 id_fk 被索引,以及代码表中 PK 的外键。

我将运行一条 SQL 语句:INSERT INTOcodes(token) VALUES ("abc123");

但是当我查看 access_codes 表时,数据与 Codes 表没有关联。

我做错了什么?

【问题讨论】:

  • 您希望访问代码表自动更新吗?
  • 外键在删除主键时对自动删除或自动更新很有用,但您必须先将一些数据插入到access_codes中。
  • @LelioFaieta,我翻了,哈哈。显然我需要回到大学,因为我现在觉得自己很愚蠢。 ID 表是自动递增的,所以现在我不确定如何让 ID 和 ID_fk 成为相同的数字。

标签: sql database phpmyadmin


【解决方案1】:

您误解了外键是什么。它们并不是将数据添加到多个表的神奇方式。它们是约束。它们限制了可以出现在access_codes.id_fk 列中的值。在这种情况下,唯一允许的值是出现在codes.id 列中的值。但是每次在codes 中插入新行时,不会在access_codes 中插入新行。你必须自己做。

附带说明 - 在这种情况下,将所有数据保存在一个表中不是更简单吗?


添加:数据库键速成课程

让我们从主键开始,它很有帮助。当今大多数 RDBMS 都将表视为大行。这些行没有排序(每次您执行select * from mytable 时,您可能会以不同的顺序将它们返回),并且没有什么可以将它们区分开来。就像你将 100 个绿球扔进一个桶里,你将无法分辨哪个球是哪个。如果你想把它们区分开来,你需要给每个球一些独特的标记,比如在每个球上写一个不同的数字或其他东西。

在使用数据库时,我们通常希望将行区分开来。每当我们对表做某事时,我们通常想要更新或删除其中的特定行,因此我们需要那个唯一的识别标记。数据库引擎制造商意识到了这一点,并且现在大多数 RDBMS 都提供了两个重要的特性 - 主键和 auto_increment 列(尽管这些特性的名称可以从 DB 到 DB)。

当您将一列标记为“主键”列时,这意味着该列将包含每一行的唯一 ID。数据库引擎将不允许您在主键列中插入具有相同值的两行(或更新一行以使其如此),因为此列的目的是唯一标识每一行.具有相同 ID 的两行会破坏此目的。

请注意,您还可以将多列作为主键。在这种情况下,每一列的值不需要唯一,但每一行的值组合在表的所有行中必须是唯一的。

此外,如果需要,您还可以拥有其他“唯一”列 - 甚至还有一个“唯一索引”,它再次使数据库拒绝插入具有非唯一值的行。

但是主键是特殊的。首先是因为它告诉任何查看该表的人“这是区分这些行的官方方式”,其次是因为大多数 RDBMS 实际上以与主键相同的顺序将行存储在磁盘上。这意味着如果您知道它的主键值,则查找一行非常快。

所以大多数人只是使用主键来识别行,而其他唯一索引很少被发现(尽管它们确实不时发生)。

Auto_increment 是一项有助于生成这些唯一 ID 的功能。如果将列(通常是整数/数字)标记为“auto_increment”(某些 RDBMS 只允许为每个表标记一列),那么在插入新行时,该列将自动获得一个比先前最大值大 1 的值在那张桌子上。唯一标识符变得容易。

现在介绍外键

由于某种原因,我们需要将两行(通常在不同的表中,但偶尔在同一个表中)链接在一起也是很常见的。

例如 - 我们公司制作的软件与停车费有关。所以我们有一张表格,列出了当前停在某个地方的所有汽车。每行代表一辆停放的汽车。它包含车牌号,停车开始时,yadda yadda。然后我们有另一个表格,列出了我们所有的客户——用户名、密码哈希、电话号码、电子邮件和作品。每行代表一个客户。另一张表格列出了我们经营的所有停车场。每个停车场一排。名称、地址、GPS 坐标、描述、价格等

这些表中的每一个都有一个 auto_increment ID 列,这也是主键。

现在,在第一个表中 - 列出停放了哪些汽车的表 - 对于每辆车,我们还想知道哪个客户停放了它,以及停在哪个停车场。所以我们有两列 - client_idlot_id。在client_id 列中,我们存储客户表的ID 的值,在lot_id 中存储手数表的值。

因此,例如,如果我们看到车牌为AB1234 的汽车停在了车上,属于ID 为222 的客户,那么我们可以转到clients 表,找到ID 为的行222 并看到它是 John Smith。同样,我们可以查找特定批次,因为我们知道它的 ID 值。

这就是外键的全部内容 - 它只是将一行的唯一 ID 放入另一行的想法,这样您就可以知道哪一行与哪一行相关(另外,这就是“关系”部分的来源来自“关系数据库”)。

现在,还有一件事要介绍 - 外键约束 - 这是 RDBMS 制造商提供的一个很棒的功能。您不是严格要求使用它,但我强烈建议您使用它。真是太好了。

基本上,它的作用是您可以告诉 RDBMS“此表中的该列实际上是该表中该列的外键”。然后数据库将帮助您确保一切都排好。

例如,如果客户表中没有 ID 为 222 的客户,我将无法为客户 222 插入停放的车辆。如果我尝试删除客户222,它不会允许我这样做,因为还有一辆车停在那里。换句话说,它确保无论我从停放的车辆表中选择哪一行,如果我从该行中获取客户端 ID,则客户端表中始终会有一行与此 ID 匹配。在地狱里我没有办法绕过它。这样可以避免很多麻烦。

【讨论】:

  • 数据库实际上已经建立,我刚刚建立了一个本地环境进行测试。数据库目前有一堆表,其中两个是访问代码和代码......我想我没有理解 PK,FK 关系,因为在我们的表上,数据是同时创建的,具有相同的 ID 关联.所以我认为这就是FK的工作方式。您是在告诉我,如果我想将数据插入到代码表中,我还必须将相同的数据插入到 access_codes 表中吗?如果我在 ID 上设置了自动增量,ID_fk 会有所不同吗?好混乱-_-
  • 我知道这可能会造成混淆。我也花了一段时间来理解这个概念。但是对您的问题的简短回答是 - 您首先在 codes 表中插入一行,然后查看自动生成的 ID 是什么。然后使用它在access_codes 表中插入一行。
  • 这是有道理的。基本上查询代码表,并使用那里的 ID 将另一个查询插入到 access_codes 表中。我想这可能是在我的服务器上的某个地方设置的。我是一名前端开发人员,曾在学校学习数据库,看看过去 4 年我忘记了多少。大声笑谢谢我会试试这个。
  • @Nick0989 - 如果您以编程方式执行此操作,则某处应该有一个 last_insert_id 函数或属性。如果最后执行的查询是 INSERT 语句,并且它插入了带有 auto_increment 列的行,则此函数/属性将包含新生成的值。这是获取插入值的正确方法。否则,如果其他人与您同时插入另一行,您将无法区分哪一行是您的。
  • @Nick0989 - 看看吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 2016-11-30
  • 2011-02-14
  • 2013-09-30
相关资源
最近更新 更多