Answers:
我会说不,并非总是如此,但大多数时候是。。
在某些情况下,您不需要代理密钥或人工密钥:
在某些情况下,过时的单调递增整数替代键也不理想。您可以使用字母数字替代键。这些可能包括:
为什么大多数时候是?该问题的最根本答案是,如果您需要修改任何表上的主键值,那简直是地狱。可以想象,由于用户可以看到或触摸的几乎所有东西都可能在某个时刻进行更新,因此使用可见键值会引起混乱。使用代理键可以防止您陷入陷阱。
话虽如此,请记住,YAGNI在应用此概念方面仍有空间。您无需将带有IDENTITY键的代码表强加到架构的每个角落,以防万一有人认为员工表中的男性符号需要从M更改为X或其他愚蠢的东西。
没有。
我要说的是,在某些情况下,单字段键至少在复合键方面不如复合键。这并不是说,如果您愿意的话,也就不应该具有单字段代理键,但是我个人更喜欢将最常用作外键目标的键称为主键。
我将在以下示例中说明我的观点,其中:
brand
是汽车品牌,例如福特,丰田等dealer
是与品牌相关的实体经销店(例如仅销售福特的福特经销店)model
是汽车的类型,例如福特福克斯,福特嘉年华等stock
每个经销商当前的前院车数如果我们为dealer
和创建一个单字段代理键,model
如下所示:
create table brand( brand_id integer primary key );
create table dealer( dealer_id integer primary key,
brand_id integer references brand )
create table model( model_id integer primary key,
brand_id integer references brand )
create table stock( model_id integer references model,
dealer_id integer references dealer,
quantity integer,
primary key(model_id, dealer_id) )
那么可以在其中插入一行stock
,将福特链接dealer
到“丰田”模型。添加brand_id references brand
到stock
只能使问题变得更糟。另一方面,如果我们将外键保留为主键的一部分,如下所示:
create table brand( brand_id integer primary key );
create table dealer( brand_id integer references brand,
dealer_id integer,
primary key(brand_id, dealer_id) )
create table model( brand_id integer references brand,
model_id integer,
primary key(brand_id, model_id) )
create table stock( brand_id integer,
model_id integer,
dealer_id integer,
quantity integer,
primary key(brand_id, model_id, dealer_id),
foreign key(brand_id, model_id) references model,
foreign key(brand_id, dealer_id) references dealer )
现在,“福特”经销商只能库存“福特”汽车的规则已由模型自然执行。
请注意,在“复合键”示例中dealer_id
,根据偏好,它可以是唯一的,也可以不是唯一的。它不必是唯一的(即备用键),但是通过使其变得唯一(可能有一点存储空间)而损失很少,并且它非常方便,因此这是我通常设置的方式,例如:
create table dealer( brand_id integer references brand,
dealer_id serial unique,
primary key(brand_id, dealer_id) )