【发布时间】: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 NULL 和 UNIQUE,因此创建复合 PRIMARY KEY 是否有意义?我“相信”插入新元素是在浪费空间和时间?
问题 2:我可以安全地使用 iso_code 在其他表中作为 FOREIGN KEY 吗?
非常感谢。
【问题讨论】:
-
您将如何在查询中加入此表?
iso_code、iso_2_alpha和iso_3_alpha是什么?不应该是iso_code唯一的吗? -
你确定要把这么复杂的验证规则放到CHECK里面吗?这将在每次插入/更新时执行。但是你真的会插入随机数据吗?如果它失败,您的代码也会从数据库收到验证错误。而且您无论如何都需要另外分析究竟是什么字段无效。
-
许多“关系纯粹主义者”认为,将一个候选键提升为比其他键更优越是 SQL 中的错误。许多“SQL 部落主义者”会告诉您,每个表都必须有一个主键。您选择哪种方式在某种程度上取决于您希望进入哪个营地:-)
-
@skyboyer - 像这样的标量计算几乎不需要时间来评估,尤其是与写入记录本身相比。我宁愿实际上强制执行完整性,当某些错误导致插入
1000而不是0或999时,允许数据库“严重失败”而不是“静默失败”。建议开销“太高”是建议不应该使用 (更昂贵的) 外键约束。 -
@skyboyer - 与
<= 4相比,它很贵。与根据内存中的索引检查键相比,这是微不足道的。与写入磁盘相比,它不存在。
标签: sql primary-key composite-primary-key