具有以下方案的复合主键或主要代理键?

时间:2015-02-27 20:55:00

标签: sql sql-server tsql

我知道它被多次询问过,但我想解释一下我的场景,看看使用Identity列作为主键而不是使用复合主键有什么好处。

我目前正在阅读两个文本文件:File1包含Make&汽车模型,而File2有制造,模型,汽车年。 Make,File2中的模型组合将始终位于File1中。

所以我创建了由MakeId(identity),MakeModel列组成的表[Car]。表[Car]的数据如下所示。 [Car]中的数据是File1:

的精确副本
[MakeId]       [Make]      [Model]
1              HONDA       ACCORD
2              HONDA       CIVIC
3              FORD        FOCUS
4              FORD        ESCORT

对于File2,我创建了包含CarYearId(标识),MakeModelYear列的表[CarYear]。 [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,为复合主键建模?鉴于我的情况,因为我有Make&在两个表中建模,我可以轻松地直接搜索第二个表而不必进行内连接。

1 个答案:

答案 0 :(得分:2)

  

File1有Make&汽车模型。 。

所以感兴趣的数据看起来像这样。

make        model
--
HONDA       ACCORD
HONDA       CIVIC
FORD        FOCUS
FORD        ESCORT

列“make”显然不是候选键。从这个数据样本中可以看出,“model”看起来像<候选键。几年前我实际上不得不研究这个问题,我发现只有几个模型由多个制造商制造,而且这些模型都不是最新的。但这并不重要。

这里的候选键是{make,model}还是{model},这个表是6NF。 1 如果我们假设唯一的候选键是{make,model},我可能会在标准SQL中实现它。

create table car_models (
  make varchar(15) not null,
  model varchar(15) not null,
  primary key (make, model)
);
  

File2有Make,Model,Car of Year。

所以感兴趣的数据看起来像这样。

make        model       year
--
HONDA       ACCORD      2002
HONDA       ACCORD      2001
HONDA       ACCORD      2004
HONDA       CIVIC       1998
FORD        FOCUS       1998
FORD        ESCORT      2001
FORD        ESCORT      2002

根据上表中关键字的假设,该表只有一个候选键,并且只有一个附加属性。它也是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)
);

这些表包含 no 冗余数据。您不能在不破坏语义或损害数据完整性的情况下删除任何列。外键在“car_model_years”的行中重复,但这并不是多余的 - 完全

  

我有什么理由不使用Make,为复合主键建模?

作为理论(关系)问题,不,没有。如果从6NF开始,则添加代理ID号非规范化该表。 (6NF需要单个候选键。)即使你添加代理ID号,你仍然必须声明{make,model}为not null unique。未能声明该约束使得表格最终看起来像这样。

model_id  make   model
--
1         Honda  Accord
2         Honda  Accord
3         Honda  Accord

作为一个实际问题,不是理论(关系)问题,这些6NF表可能比使用代理ID号更好地执行它们。例如,基于make和model的“car_model_years”查询通常会使用仅索引扫描 - 它们根本不必读取基表。

另一个实际问题是,除了id号之外,某些应用程序框架与任何密钥的处理都很差。恕我直言,这证明使用更好的框架是合理的,但不会损害数据库的结构。

<小时/> 1.“......'常规'relvar在6NF中,当且仅当它由一个键组成时,加上最多一个附加属性。”日期,CJ,深度数据库:从业者的关系理论,第147页。常规的relvar是非时间的relvar。