MySQL - 升级主键

本文关键字:MySQL | 更新日期: 2023-09-27 18:34:44

我真的不知道如何命名这个。问题是我一般都是数据库的乞丐,我想知道这是否是一个好习惯。

所以我的数据库中有一些类似于这个的表:

create table AAA(
id_aaa int not null auto_increment,
primary key (id_aaa)
);
create table BBB(
id_bbb int not null auto_increment,
id_aaa_AAA int not null,
primary key (id_bbb),
foreign key (id_aaa_AAA) references AAA (id_aaa)
);
create table CCC(
id_ccc int not null auto_increment,
id_aaa_AAA int not null,
id_bbb_BBB int not null,
primary key (id_ccc),
foreign key (id_aaa_AAA) references AAA (id_aaa),
foreign key (id_bbb_BBB) references BBB (id_bbb)
);

ERD:

AAA (1-n) BBB (1-n) CCC

是否可以在CCC中添加AAA的主键以获得"更快的可访问性",因为我可以通过BBB访问?

MySQL - 升级主键

简短的回答是:不要这样做。您将冗余存储数据,这可能会在一段时间内导致错误 - 如果突然将 id_aaa_AAA = 1 的 CCC 记录指向 id_aaa_AAA = 2 的 BBB 记录怎么办?

长答案是:有自然钥匙和人工(技术(钥匙......

通常,您具有标识实体的自然键(例如员工编号、国际物料编号等(。这是一个公司,员工和销售的数据库。粗体列是自然键,可用作表的主键:

  • 公司(ILN、company_name等(

ILN(国际位置号码(唯一标识公司。

  • 员工(ILN、employee_no、employee_name等(
员工

在其公司中有一个员工编号。但它只有在与公司相结合时才是独一无二的。(即,在公司 A 中具有 #123 的员工当然是公司 B 中员工 #123 的其他人。

  • 销售额(ILN、employee_no、年份、总计(

员工一年卖了多少钱?记录由 ILN + 员工编号标识,以标识员工和年份。

现在许多人更喜欢设计一个带有技术ID的数据库,因为他们发现这个概念更灵活,而且通常有些实体根本没有自然键(例如,地址仅由其所有组件的总和标识,因此您更愿意创建一个人工ID在其他表中引用它(。以下是具有技术 ID 的相同数据库:

  • 公司(company_id,ILN,company_name等(
  • 员工(employee_id、employee_no、employee_name、company_id等(
  • 销售额(sales_id、employee_id、年份、总计(

在这里,每个表都有一个唯一的技术ID,通常是主键。(当然,你也会对company(iln)employee(employee_no, company_id)sales(employee_id, year)仍然有独特的约束。没有冗余,因此 ILN 仅存储在表公司中。如果你想要一家公司在2015年的销售额总和,你必须相应地浏览所有表格。

使用上述自然键,您不会。您将在所有表中都有 ILN,它仍然不是多余的,因为它是所有表的键的一部分(即,如果您从员工或销售中删除 ILN,您将不知道记录指的是哪个员工(。在这里,您只能访问销售表以获取公司 2015 年的销售额总和。

我发现使用自然键更舒服,但是正确设计这样一个数据库需要一些时间,而且通常你仍然需要发明键,如地址,如前所述。但数据访问通常更直接,即使具有技术 ID 无法提供的深度层次结构,也能保证数据一致性。

所以长答案是:决定是否要使用自然键。

尝试在数据库中存储尽可能少的数据(即规范化数据(。

在表CCC中拥有冗余信息只会再次困扰您。如果您更新 BBB 中的行以引用 AAA 中的新值,那么您将有义务更新 CCC 中引用 BBB 中该行的所有行。在这个简单的例子中没什么大不了的,但是一旦你超过5张表,这可能会变得非常混乱,很难跟踪。