我在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_code
,iso_2_alpha
,iso_3_alpha
)都是NOT NULL
,因此UNIQUE
确实可以创建复合{{ 1}}?我“相信”插入新元素会浪费时间和空间吗?
问题2:我可以安全地使用PRIMARY KEY
是其他表中的iso_code
吗?
非常感谢。
答案 0 :(得分:3)
因为所有主列(iso_code,iso_2_alpha,iso_3_alpha)都不为空,并且UNIQUE创建复合主键确实有意义吗?我“相信”插入新元素会浪费时间和空间吗?
您建议的PK是现有密钥的超级密钥。本身并不必要。您可以选择将唯一键约束之一声明为PK,但这不是必需的。
我可以安全地使用iso_code作为其他表中的FOREIGN KEY吗?
如果您还将iso_code
标记为该表中的唯一键,则应该可以正常工作。
有人会建议每个表始终都有一个自动生成的列,标记为PK。只要您还强制执行逻辑键,就可以了。不幸的是,许多人只会创建该自动PK而无需创建其他密钥,这意味着您的数据是无稽之谈。
(当前)您已选择仅具有逻辑键。我认为在这种情况下还可以,特别是因为几个(iso_code
,iso_2_alpha
和iso_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列,恕我直言。