【问题标题】:Best practice for MySql unique identifying key columnsMySql 唯一标识键列的最佳实践
【发布时间】:2019-12-04 08:20:12
【问题描述】:

这只是一个概括的例子。我有一个包含几十行数据的静态 MySQL 数据库参考表。该表的结构如下所示:

video_games
id             int(11)
release_date   datetime
title          varchar(64)
msrp           float

我有一个名为“users”的单独表,其中包含一个“favorite_video_game_id”列,该列可以指向“video_games”中的“id”列。

在我建立的一个网站上,我有一个特殊页面,专门用于显示几个特定游戏(“守望先锋”、“魔兽争霸”和“暗黑破坏神”)粉丝的用户名。为了拉回游戏信息和喜欢的用户,我有一个类似下面的mysql语句:

select u.*, vg.* 
from users u, video_games vg 
where u.favorite_video_game_id = vg.id and vg.title= 'Warcraft';

在某个时候,我意识到我想在数据库中为游戏命名一个更具体的名称,“魔兽世界”,因此我更新了数据库中的名称。然而,当我回到我的页面时,我意识到游戏信息和信息列表显示为空,因为“标题”列已更改,我现在需要更新我的所有代码。

当我意识到我想要扩展为更完整的名称的所有标题,以及我需要在网站上进行的所有代码更改时,我觉得我的 PHP 代码与 SQL 紧密耦合数据,就像我将内容数据硬编码到我的 PHP 文件中一样。我的第一个想法是更改 mysql 代码以直接引用 ID,如下所示:

select u.*, vg.* 
from users u, video_games vg 
where u.favorite_video_game_id = vg.id and vg.id= 13;

但是,我了解到不鼓励像这样直接使用主键列,因为将来可能会出现必须更改 id 或将数据传输到另一个数据库供应商的情况,并且 id 会不再正确。

我的下一个想法是添加另一个索引键列,可能是随机哈希值,这也是视频游戏独有的,不会遇到上述问题。但是当已经有 id 列时添加另一个唯一键列似乎有点奇怪/冗余,我想知道我是否可能会丢失/忽略一些东西,只要不将我的 PHP 耦合到内容列中的唯一标识行数据库。

在这种情况下,最佳设计实践是什么?谢谢。

【问题讨论】:

  • 只是好奇,您从哪里读到不鼓励使用主键列?以前从未听说过这个,我想找出它这么说的原因。
  • 无论是 ID 还是电影标题,数据都可能发生变化(无论风险多么小)。我想说在你不知道的情况下更改 ID 的风险相当小,因为这会严重限制典型关系数据库的可靠性。如果表格被视为静态,则标题更改的风险可能同样小。如果您必须对引用条目的值进行硬编码,我可能会将它们更新为新标题,特别是如果这只是一次性更改。
  • 话虽如此,如果您担心 ID 发生变化(例如,您可能会更改数据库引擎或使用分布式环境),您可以使用服务器生成的 ID 而不是数据库 -生成的 ID。见Why Did We Shift Away From Database-Generated Ids?
  • @catcon 这是我在从事 Java 开发并在 Oracle RDBMS 工作时工作的一家大型(阅读:数百万美元的全球)咨询公司的标准经验法则。 TBH,自从我从事 PHP 开发以来,我一直对我从小公司的 Web 开发人员那里看到的一些数据库实践感到震惊,所以我试图在这里寻找最佳实践来处理这些问题耦合问题。
  • 你也可以考虑问dba.stackexchange.com

标签: php mysql database-design


【解决方案1】:

我投了第一个答案,因为它基本上描述了你应该如何设计你的数据库结构,他是对的。如果您必须在第三张表中使用唯一键,您可以使用emailphone 或任何其他键,它们在您的用户表中是唯一的,并且在游戏表中以相同的方式:如果您在同样,欢迎您在第三张表中使用它。基本上第三个表是做什么的,它只是将你的两个表关联起来,比如用户和游戏。

【讨论】:

    【解决方案2】:

    为了形式化几个 cmets 已经说过的内容,使用表的主键建立关系没有任何问题。事实上,这是意料之中的,并且是“最佳实践”。您永远不应尝试基于 volatile 字段创建关系,除非您添加安全机制以在值更改时更新所有引用。其中一些是内置在 MySQL 中的,但主键是一块稳定的岩石,你可以把船系在上面。

    简单地说,项目的主键永远不会改变。如果它是不同的主键,则根据定义,它是不同的项目。

    我感觉你从根本上理解这一点,但要么误读了好建议,要么完全阅读了坏建议。但我在这里告诉你——这就是主键的用途。在您的favorite_video_game_id 列中使用game_id,然后愉快地继续前进。

    【讨论】:

    • 考虑因素可能包括:“如果我们想用一个[无法生成]自动增量主键的数据存储系统来改变怎么办?... [E]每个数据存储系统都有不同的生成这些标识符的方法可能[生成]不同的原始类型.... [W]当我们的 SQL Server 数据库中有一个带有生成的主键的表时,我们没有简单的方法来水平扩展这个表分布式环境。” --Id Generation on the Server vs. Database.
    • 这就是为什么我提出了一个基于电子邮件或任何其他字段的唯一键,这将在这两个表中是唯一的。在这种情况下,我们跳过处理其他数据存储中是否生成主键。
    猜你喜欢
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 2020-07-17
    相关资源
    最近更新 更多