具有以下场景的复合主键或主代理键?
Composite primary key or primary surrogate key with following scenario?
我知道这个问题已经被问过很多次了,但我想解释一下我的情况,看看使用标识列作为主键而不是使用复合主键是否有任何好处。
我目前正在阅读两个文本文件:文件 1 包含汽车制造商和型号,而文件 2 包含汽车制造商、型号和年份。 File2 中的 Make、Model 组合将始终在 File1 中。
所以我创建了 table [Car],由 MakeId(标识)、Make
和 Model
列组成。 table [Car] 的数据如下所示。 [Car] 中的数据是 File1 的精确副本:
[MakeId] [Make] [Model]
1 HONDA ACCORD
2 HONDA CIVIC
3 FORD FOCUS
4 FORD ESCORT
对于 File2,我创建了 table [CarYear],其列为 CarYearId
(身份)、Make
、Model
、Year
。 [CarYear] 中的数据是 File2 的精确副本:
[CarYearId] [Make] [Model] [Year]
1 HONDA ACCORD 2002
2 HONDA ACCORD 2001
3 HONDA ACCORD 2004
4 HONDA CIVIC 1998
5 FORD FOCUS 1998
6 FORD ESCORT 2001
7 FORD ESCORT 2002
为什么我不应该使用 Make, Model 复合主键?鉴于我的情况,因为我在两个 table 中都有 Make & Model,所以我可以轻松地直接搜索第二个 table 而不必进行内部连接。
File1 has Make & Model of car . . .
所以感兴趣的数据看起来像这样。
make model
--
HONDA ACCORD
HONDA CIVIC
FORD FOCUS
FORD ESCORT
列"make"显然不是候选键。据此数据样本可以看出,"model" 看起来 像一个候选键。事实上,几年前我不得不研究这个问题,我发现只有几个模型是由多个制造商制造的,其中 none 个是最新的。但这并不重要。
无论这里的候选key是{make,model}还是{model},这个table在6NF中。1如果我们假设唯一的候选key是 {make, model},我可能会在标准 SQL.
中这样实现它
create table car_models (
make varchar(15) not null,
model varchar(15) not null,
primary key (make, model)
);
File2 has Make, Model, Year of car.
所以感兴趣的数据看起来像这样。
make model year
--
HONDA ACCORD 2002
HONDA ACCORD 2001
HONDA ACCORD 2004
HONDA CIVIC 1998
FORD FOCUS 1998
FORD ESCORT 2001
FORD ESCORT 2002
按照前面table中对key的假设,这个table只有一个候选key,而且只有一个附加属性。它也属于 6NF。 SQL 版本可能如下所示。
create table car_model_years (
make varchar(15) not null,
model varchar(15) not null,
model_year integer not null
check (model_year between 1886 and 2099),
primary key (make, model, model_year),
foreign key (make, model) references car_models (make, model)
);
这些table有没有冗余数据。您不能在不破坏语义或损害数据完整性的情况下删除任何列。外键在 "car_model_years" 的行中重复,但这不是多余的——这 正是 外键是 for.
Is there any reason why I shouldn't use Make, Model a composite primary key?
作为理论(关系)问题,不,没有。如果您从 6NF 开始,添加代理 ID 编号 反规范化 即 table。 (6NF 需要一个 单一 候选密钥。)即使你 do 添加代理 ID 号码,你 still 必须将 {make, model} 声明为 not null unique
。未能声明该约束会使 table 最终看起来像这样。
model_id make model
--
1 Honda Accord
2 Honda Accord
3 Honda Accord
作为一个实际问题,而不是理论(关系)问题,这些 6NF tables 可能比使用代理 ID 号对它们进行非规范化表现得更好。例如,基于品牌和型号的 "car_model_years" 查询通常会使用仅索引扫描——它们根本不需要读取基础 table。
作为另一个实际问题,某些应用程序框架无法很好地处理除 ID 号之外的任何键。恕我直言,这证明使用更好的框架是合理的,但不会影响数据库的结构。
1. “...一个 'regular' 关系变量在 6NF 中当且仅当它由一个键组成,最多加上一个附加属性。” Date,CJ,深度数据库:从业者关系理论,第 147 页。常规关系变量是非时间关系变量。
我知道这个问题已经被问过很多次了,但我想解释一下我的情况,看看使用标识列作为主键而不是使用复合主键是否有任何好处。
我目前正在阅读两个文本文件:文件 1 包含汽车制造商和型号,而文件 2 包含汽车制造商、型号和年份。 File2 中的 Make、Model 组合将始终在 File1 中。
所以我创建了 table [Car],由 MakeId(标识)、Make
和 Model
列组成。 table [Car] 的数据如下所示。 [Car] 中的数据是 File1 的精确副本:
[MakeId] [Make] [Model]
1 HONDA ACCORD
2 HONDA CIVIC
3 FORD FOCUS
4 FORD ESCORT
对于 File2,我创建了 table [CarYear],其列为 CarYearId
(身份)、Make
、Model
、Year
。 [CarYear] 中的数据是 File2 的精确副本:
[CarYearId] [Make] [Model] [Year]
1 HONDA ACCORD 2002
2 HONDA ACCORD 2001
3 HONDA ACCORD 2004
4 HONDA CIVIC 1998
5 FORD FOCUS 1998
6 FORD ESCORT 2001
7 FORD ESCORT 2002
为什么我不应该使用 Make, Model 复合主键?鉴于我的情况,因为我在两个 table 中都有 Make & Model,所以我可以轻松地直接搜索第二个 table 而不必进行内部连接。
File1 has Make & Model of car . . .
所以感兴趣的数据看起来像这样。
make model -- HONDA ACCORD HONDA CIVIC FORD FOCUS FORD ESCORT
列"make"显然不是候选键。据此数据样本可以看出,"model" 看起来 像一个候选键。事实上,几年前我不得不研究这个问题,我发现只有几个模型是由多个制造商制造的,其中 none 个是最新的。但这并不重要。
无论这里的候选key是{make,model}还是{model},这个table在6NF中。1如果我们假设唯一的候选key是 {make, model},我可能会在标准 SQL.
中这样实现它create table car_models (
make varchar(15) not null,
model varchar(15) not null,
primary key (make, model)
);
File2 has Make, Model, Year of car.
所以感兴趣的数据看起来像这样。
make model year -- HONDA ACCORD 2002 HONDA ACCORD 2001 HONDA ACCORD 2004 HONDA CIVIC 1998 FORD FOCUS 1998 FORD ESCORT 2001 FORD ESCORT 2002
按照前面table中对key的假设,这个table只有一个候选key,而且只有一个附加属性。它也属于 6NF。 SQL 版本可能如下所示。
create table car_model_years (
make varchar(15) not null,
model varchar(15) not null,
model_year integer not null
check (model_year between 1886 and 2099),
primary key (make, model, model_year),
foreign key (make, model) references car_models (make, model)
);
这些table有没有冗余数据。您不能在不破坏语义或损害数据完整性的情况下删除任何列。外键在 "car_model_years" 的行中重复,但这不是多余的——这 正是 外键是 for.
Is there any reason why I shouldn't use Make, Model a composite primary key?
作为理论(关系)问题,不,没有。如果您从 6NF 开始,添加代理 ID 编号 反规范化 即 table。 (6NF 需要一个 单一 候选密钥。)即使你 do 添加代理 ID 号码,你 still 必须将 {make, model} 声明为 not null unique
。未能声明该约束会使 table 最终看起来像这样。
model_id make model -- 1 Honda Accord 2 Honda Accord 3 Honda Accord
作为一个实际问题,而不是理论(关系)问题,这些 6NF tables 可能比使用代理 ID 号对它们进行非规范化表现得更好。例如,基于品牌和型号的 "car_model_years" 查询通常会使用仅索引扫描——它们根本不需要读取基础 table。
作为另一个实际问题,某些应用程序框架无法很好地处理除 ID 号之外的任何键。恕我直言,这证明使用更好的框架是合理的,但不会影响数据库的结构。
1. “...一个 'regular' 关系变量在 6NF 中当且仅当它由一个键组成,最多加上一个附加属性。” Date,CJ,深度数据库:从业者关系理论,第 147 页。常规关系变量是非时间关系变量。