使用UNIQUE NOT NULL列时,我真的需要PRIMARY KEY吗?

时间:2018-09-09 08:10:22

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

我在SQL方面的知识有限,很高兴有人在以下情况下帮助我阐明PRIMARY KEY的使用。我创建了一个表来支持ISO国家信息。我正在使用MariaDB 10,但我认为这与我所遇到的问题无关?(p)

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_codeiso_2_alphaiso_3_alpha)都是NOT NULL,因此UNIQUE确实可以创建复合{{ 1}}?我“相信”插入新元素会浪费时间和空间吗?

问题2:我可以安全地使用PRIMARY KEY是其他表中的iso_code吗?

非常感谢。

2 个答案:

答案 0 :(得分:3)

  

因为所有主列(iso_code,iso_2_alpha,iso_3_alpha)都不为空,并且UNIQUE创建复合主键确实有意义吗?我“相信”插入新元素会浪费时间和空间吗?

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

  

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

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

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

(当前)您已选择仅具有逻辑键。我认为在这种情况下还可以,特别是因为几个(iso_codeiso_2_alphaiso_3_alpha)可能比推荐的自动生成的列更紧凑。

答案 1 :(得分:0)

无法评论性能和效率,但是复合键的一件事是,当您将它们用作主键时,必须在外键中重复它们。也就是说,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列,恕我直言。