【问题标题】:Do I really need PRIMARY KEY when using UNIQUE NOT NULL columns?使用 UNIQUE NOT NULL 列时我真的需要 PRIMARY KEY 吗?
【发布时间】:2018-09-09 08:10:21
【问题描述】:

我在 SQL 方面的知识有限,如果有人能帮助我澄清PRIMARY KEY 在以下情况下的用法,我将不胜感激。我创建了一个表格来支持 ISO 国家信息。我正在使用 MariaDB 10,但我相信这与我遇到的问题无关(?)

CREATE TABLE IF NOT EXISTS python.country
(
   iso_code    INTEGER(   3) NOT NULL     ,
   iso_2_alpha VARCHAR(   2) NOT NULL     ,
   iso_3_alpha VARCHAR(   3) NOT NULL     ,
   short_name  VARCHAR(  32) NOT NULL     ,
   long_name   VARCHAR(  64) NOT NULL     ,
   flag_link   VARCHAR(2000) DEFAULT(NULL),

   CONSTRAINT  CK_iso_code       CHECK       (iso_code > 0 AND iso_code <= 999)                                ,
   CONSTRAINT  CK_iso_alpha      CHECK       (
                                              iso_2_alpha RLIKE BINARY '^[A-Z]+$' AND LENGTH(iso_2_alpha) = 2 
                                              AND 
                                              iso_3_alpha RLIKE BINARY '^[A-Z]+$' AND LENGTH(iso_3_alpha) = 3
                                             )                                                                 ,  
   CONSTRAINT  CK_names          CHECK       (
                                              short_name RLIKE '^\\p{L}+(\\.?[[:blank:]]\\p{L}+)*\\p{L}+$'
                                              AND 
                                              long_name  RLIKE '^\\p{L}+(\\.?[[:blank:]]\\p{L}+)*\\p{L}+$'
                                             )                                                                 ,
   CONSTRAINT  UN_short_name     UNIQUE      (short_name)                                                      ,
   CONSTRAINT  UN_long_name      UNIQUE      (long_name)                                                       ,
   CONSTRAINT  UN_iso_2_alpha    UNIQUE      (iso_2_alpha)                                                     ,
   CONSTRAINT  UN_iso_3_alpha    UNIQUE      (iso_3_alpha)                                                       
   -- ???
   -- CONSTRAINT  PK_country        PRIMARY KEY (iso_code,iso_2_alpha,iso_3_alpha)

); -- ENGINE = 'InnoDB';

问题 1:由于所有主要列 (iso_code,iso_2_alpha,iso_3_alpha) 都是 NOT NULLUNIQUE,因此创建复合 PRIMARY KEY 是否有意义?我“相信”插入新元素是在浪费空间和时间?

问题 2:我可以安全地使用 iso_code 在其他表中作为 FOREIGN KEY 吗?

非常感谢。

【问题讨论】:

  • 您将如何在查询中加入此表? iso_codeiso_2_alphaiso_3_alpha 是什么?不应该是 iso_code 唯一的吗?
  • 你确定要把这么复杂的验证规则放到CHECK里面吗?这将在每次插入/更新时执行。但是你真的会插入随机数据吗?如果它失败,您的代码也会从数据库收到验证错误。而且您无论如何都需要另外分析究竟是什么字段无效。
  • 许多“关系纯粹主义者”认为,将一个候选键提升为比其他键更优越是 SQL 中的错误。许多“SQL 部落主义者”会告诉您,每个表都必须有一个主键。您选择哪种方式在某种程度上取决于您希望进入哪个营地:-)
  • @skyboyer - 像这样的标量计算几乎不需要时间来评估,尤其是与写入记录本身相比。我宁愿实际上强制执行完整性,当某些错误导致插入1000 而不是0999 时,允许数据库“严重失败”而不是“静默失败”。建议开销“太高”是建议不应该使用 (更昂贵的) 外键约束。
  • @skyboyer - 与 &lt;= 4 相比,它很贵。与根据内存中的索引检查键相比,这是微不足道的。与写入磁盘相比,它不存在。

标签: sql primary-key composite-primary-key


【解决方案1】:

由于所有主要列(iso_code、iso_2_alpha、iso_3_alpha)都不是 NULL 并且 UNIQUE 是否有意义创建复合主键?我“相信”插入新元素是在浪费空间和时间?

您建议的 PK 是现有密钥的超级密钥。它本身没有必要。您可以选择将您的唯一键约束之一声明为 PK,但这不是必需的。

我可以安全地使用 iso_code 作为其他表中的 FOREIGN KEY 吗?

如果您还在此表中将 iso_code 标记为唯一键,则应该可以正常工作。

有些人会建议每个表总是有一个自动生成的列标记为 PK。只要您强制执行逻辑键就可以了。不幸的是,许多人只会创建自动 PK 而没有其他密钥,这意味着您的数据是无稽之谈。

您已选择(当前)仅使用逻辑键。我认为在这种情况下这很好,尤其是几个(iso_codeiso_2_alphaiso_3_alpha)可能比推荐的自动生成列更紧凑。

【讨论】:

  • 谢谢。你已经明白了我的问题的全部意义。是的,你是对的,它是 ISO 3166,这就是为什么我没有使用任何类型的自动生成的 PK。请允许我再问一个问题。我可以根据你的回答假设这个“TABLE”的设计是完全可以接受的吗?
  • @JacintoResende - 会对这个设计非常满意,但其他人可能不同意,我们将开始进入“主要基于意见”的领域并结束。跨度>
  • @philipxy - 我认为 OP 不是在谈论复合键,而是在谈论多个独立的唯一键。
  • @JacintoResende 如果你想要一个复合 FK,那么你必须声明引用的 coumn 设置一个复合 PK 或 UNIQUE,因为这是规则,尽管限制/强制由(每个)组成部分暗示独特的。如果多个 FK 列应该引用同一个实体/行,那么您确实需要一个复合 FK。
  • @MatBailie 我只是告诉提问者规则。他们询问有关声明复合 PK 的问题,我的评论说他们何时可能需要声明复合 PK 或 UNIQUE。
【解决方案2】:

无法评论性能和效率,但复合键的一件事是,当您将它们用作主键时,您必须在外键中重复它们。即,PK iso_code、iso_2_alpha、iso_3_alpha 将是所有相关表中的附加 FK 列。然后,您还必须在 SQL 查询中按这 3 列进行查询。当您可以简单地使用通用的、独特的自生成列时,有点 PITA IMO。

如果您可以使用 iso_code,并且您确定永远不会有机会要求插入具有不同 iso_2_alpha、iso_3_alpha 的重复 iso_code,那么请继续。但是,您应该使用与业务无关的新的专用 id 列,恕我直言。

【讨论】:

  • 我从命名中得知这是ISO 3166 的表示。这是代表国家的国际标准。 ISO 不会引入重复项。
  • @Ichirichi:谢谢。这也是问题之一。我试图让“事情”尽可能简单。另一方面,正如 Damien_The_Unbeliever 所说,我使用的是 ISO 3166。所以我保证这些代码保持唯一。
  • 使用代理键只是将问题转移到不同的地方。在逻辑键和代理键之间仍然需要一个映射,以便强制逻辑键是唯一的。任何允许单个逻辑键引用多个代理键的模式都是失败的。因此,此表上的唯一约束是有意义的。然后,根据引用它的表,拥有代理键​​可能被认为是多余的或有用的。
猜你喜欢
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2015-04-22
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多