mysql - 数据库设计 : Composite key vs one column primary key

标签 mysql database-design primary-key normalization composite-key

我正在处理的 Web 应用程序遇到了意外的“错误”- 应用程序的数据库有两个表(以及许多其他表),分别称为“州”和“城市”。

'States' 表字段:

-------------------------------------------
idStates   |   State   |   Lat   |   Long
-------------------------------------------

'idStates' 是一个自动递增的主键。

城市”表字段:

----------------------------------------------------------
idAreaCode   |   idStates   |   City   |   Lat   |   Long
----------------------------------------------------------

'idAreaCode' 是由国家代码 + 区号组成的主键(例如 91422,其中 91 是印度的国家代码,422 是印度城市的区号)。 “idStates”是从“States”表派生的外键,用于将“Cities”表中的每个城市与其对应的州相关联。

我们认为国家代码 + 区号组合对于每个城市都是唯一的,因此可以安全地用作主键。一切正常。但是在印度的一个地方发现了数据库设计中一个意想不到的“缺陷”——印度和美国一样是联邦制民主国家,在地理上分为许多州或联邦领土。州和联邦领土数据都存储在“States”表中。但是,有一个位置 - Chandigarh - 属于两个州(哈里亚纳邦旁遮普邦)并且本身也是一个联邦领土。

显然,当前的数据库设计不允许我们存储城市“Chandigarh”的多个记录。

建议的解决方案之一是创建一个组合列“idAreaCode”和“idStates”的主键。

我想知道这是否是可能的最佳解决方案?

(仅供引用:我们将 MySQL 与 InnoDB 引擎结合使用)。


更多信息:

  • 数据库存储每个城市的气象信息。因此,州和城市是每个查询的起点。
  • 每天都会使用 CSV 文件插入每个城市的新数据。 CSV 文件包含一个 idStates(代表州)和 idAreaCode(代表城市)列,用于标识每条记录。
  • 数据库规范化对我们很重要。

注意:城市表不使用自动递增主键的原因是数据库使用 CSV 文件(由另一个应用程序生成)每天/每小时更新一次。 CSV 文件中的每条记录都由 idStates 和 idAreaCode 列标识。因此,最好在城市表中使用的主键对于每个城市都是相同的,即使该表被删除并再次刷新也是如此。邮政编码(或 pin 代码)和区号(或 STD 代码)符合唯一、静态(不经常更改)的标准,并且可以轻松获得现成的列表。 (我们现在决定使用区号,因为印度正在将其个人识别码更新为新格式)。

The solution we decided on was to handle this at the application level instead of making changes to the database design. In the database we will only be storing one record of 'Chandigarh'. In the application we've created a flag for any search for 'Chandigarh, Punjab' or 'Chandigarh, Haryana' to redirect search to this record. Yeah, it's not ideal, but an acceptable compromise since this is the ONLY exception we've come across so far.

最佳答案

听起来您正在为电话簿收集数据。你是?为什么状态对你很重要?这个问题的答案可能会决定哪种数据库设计最适合您。

您可能认为城市是什么显而易见。它不是。这取决于您将如何处理数据。在美国,有一个名为 MSA(大都会统计区)的单位。堪萨斯城 MSA 横跨堪萨斯州堪萨斯城和密苏里州堪萨斯城。 MSA 单位是否有意义取决于数据的预期用途。 如果您在美国使用区号来确定城市,您最终会得到与 MSA 截然不同的分组。同样,这取决于您将如何处理数据。

一般来说,每当政治分割的等级模式崩溃时,最普遍的解决方案就是考虑多对多关系。解决这个问题的方式与解决其他多对多问题的方式相同。通过创建一个带有两个外键的新表。在这种情况下,外键是 IdAreacode 和 IdStates。

现在您可以在多个州拥有一个区号,并且一个州可以跨越多个区号。接受这种额外的开销来覆盖一个异常似乎是一种耻辱。你知道你发现的异常是否只是冰山一角,还有很多这样的异常?

关于mysql - 数据库设计 : Composite key vs one column primary key,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1264248/

相关文章:

php - 用sql计算php中的行数

php - Sql 不会在 WHERE 中获取值

database-design - 产品评论投票如何在数据库中建模?

c# - 为什么大多数人说数据服务和数据库是系统中最重要的部分?

sql - 在数据库外存储主键生成器的安全方法?

mysql - 创建一个学生ID以字母开头的表 - mysql

mysql - 如何获取按匹配属性数量排序的查询行?

mysql - 设计 mysql 表时的外键放置

asp.net-mvc - 为什么映射对象 PK 会破坏 ExpressMapper?

PHP 搜索多个表