3

我的数据库设计目前处于 3NF 阶段。值得关注的问题是外键,在某些情况下是复合键。

我的问题是这样的:

如果与复合键/外键关联的属性不依赖于主键,您能否移动复合键和/或外键来创建其他表?

由于这个链接,我认为答案是肯定的:

第三范式中是否包含外键?
最佳答案:仅仅因为它是外键并不意味着它也不能被视为主键的属性。它是一个外键开始的事实意味着它定义了与另一个表的关系,因此不会违反 [...] 3NF。
-- TheMadProfessor
https://answers.yahoo.com/question/index?qid=20081117095121AAXWBbX#

这让我想知道我当前正在处理的标准化阶段是否实际上处于 3NF 中。

我不能就这个问题发布我的表格,因为我是新手并且没有足够的积分。

4

3 回答 3

4

前言

在纯关系数据库理论中,没有什么可以阻止您拥有复合主键 (PK),并且您可以拥有引用它们的外键 (FK),并且这些 FK 也必然是复合的。有些软件在组合键方面有困难,所以你经常会发现人们添加了一个 ID 列,其中包含一个自动生成的数字,然后将其指定为表的 PK。然后,其他表可以具有引用(简单)ID 列的(简单)FK。一个不常见的错误是忘记原始复合 PK 仍然是候选键 (CK),它的唯一性应该由 DBMS 通过对表的唯一约束来强制执行;它成为备用密钥(AK)。

导流

CKs、AKs 和 PKs 的系统是这样工作的:

  • 每个 CK 都是一组(一个或多个)列,它是表中每行数据其余部分中数据的唯一标识符。
  • 一个CK可以被指定为PK
  • 其他 CK 成为 AK。

考虑这张表:

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL PRIMARY KEY
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE,
    name            CHAR(20) NOT NULL UNIQUE,
    atomic_weight   DECIMAL(8,4) NOT NULL,
    period          SMALLINT NOT NULL
                    CHECK (period BETWEEN 1 AND 7),
    group           CHAR(2) NOT NULL
                    -- 'L' for Lanthanoids, 'A' for Actinoids
                    CHECK (group IN ('1', '2', 'L', 'A', '3', '4', '5', '6',
                                     '7', '8', '9', '10', '11', '12', '13',
                                     '14', '15', '16', '17', '18')),
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

atomic_number中的每一个都是候选键。对于化学来说,作为主键最方便;对于物理来说,最方便的。与同位素等相关的表格引用了该列,但与化学化合物相关的表格引用了该列。这里的三个CK都很简单;另一方面,同位素表有一个由元素的原子序数(质子数)和中子数组成的化合物PK。symbolnamesymbolatomic_numberatomic_numbersymbol

回答

回到你的问题,你的数据很可能是 3NF,或者更有可能是 BCNF(正式比 3NF 更强)。

在我们评估您的设计之前,您必须向我们展示您的表模式并指定适用于列的约束(功能依赖等)。但是,您所描述的任何东西都没有先验地阻止它被很好地规范化。

于 2012-09-07T18:41:45.460 回答
3

我不确定我是否理解你的问题。如果您要问,“您能否在不违反 3NF 的情况下在表中拥有外键?” 答案是肯定的,肯定的。规范化的任何阶段都没有说您应该消除外键。事实上,在不使用外键的情况下,几乎不可能标准化除了最琐碎的数据之外的所有数据。

** 更新 **

好的,也许现在我明白了你的问题,但我想你已经自己回答了。是的,在完全规范化的数据库中,您不应该有非关键依赖项。如果您有不依赖于 PK 的 FK,则应将它们移至另一个表。

举一个简单的例子,假设你想跟踪人们,他们居住的城市,以及该城市所在的国家。所以对于你的初稿,你制作了这样的结构:(星号标记 PK。)

Person (person_id*, person_name, city_id, country_id)
City (city_id*, city_name)
Country (country_id*, country_name)

这不是标准化的。无论我们谈论的是哪个城市的居民,一个城市都在同一个国家。当我们谈论皮埃尔时,巴黎不在法国,而当我们谈论弗朗索瓦时,巴黎不在法国。(如果有两个同名的城市,当然是不同的城市,应该有不同的记录。我想一个城市可以跨越国界,但为了我们的目的,我们假设如果它是,我们认为它是两个城市碰巧碰到。他们肯定会有不同的市政府、不同的邮政系统等)所以我们有一个非关键依赖。country_id 取决于 city_id,而不是 person_id。

所以为了规范这个模式,我们应该将 country_id 移动到一个表中,它只依赖于 PK。据推测,城市表:

Person (person_id*, person_name, city_id)
City (city_id*, city_name, country_id)
Country (country_id*, country_name)
于 2012-09-07T17:49:57.723 回答
0

你了解什么是 FD(功能依赖)吗?FD 是在两个属性集之间带有箭头的表达式。给定一个表和一个 FD,说 FD 在表中保存或表具有 FD 或表满足 FD 表示第一个属性集的所有子行与第二个属性集的相同子行出现。

您是否了解规范化涉及 CK(候选键)?独立于规范化,我们可以将一个 CK 称为 PK(主键)和其他 AK(备用键)。

你了解什么是 FK(外键)吗?给定一个数据库、一个表和一个属性列表,说该列表是一个 FK,它引用了某个表中的某个属性列表,那么第一个表中属性的每个值列表也是第一个表中属性值的列表第二个表,这些属性形成 CK(候选键)。

规范化使用 FD 和 JD(连接依赖项)通过连接回该表的投影来替换表。FK(外键)与规范化无关。这与表是否处于给定的 NF(正常形式)以及分解为给定的 NF 相关。您链接到的答案还说 FK 与表是否在 3NF 中无关——首先针对特定情况,然后针对一般情况。

因为组件共享原始表中的列值,所以一些 FK 将来自规范化。就像各种表格及其 PK、AK、CK、超级密钥、FD 和 JD 一样。那是标准化输出,而不是输入。

由于规范化通过它们的投影来替换表,因此原始 & 组件之间共有的列集必须包含相同的子行值。这是一个 EQD(平等依赖)。因此,形成 CK 的子行值将具有来自标准化的 FK。

但是在规范化过程中,我们经常看到我们想用一些投影替换一个表,而其他表至少具有投影的子行。然后,投影中的公共子行必须出现在展开的组件中,但反之则不然。那是一个IND(包含依赖)。当公共列在作为投影超集的表中形成 CK 时,仍然会有 FK。这样的设计更改不是规范化,它只是您在规范化过程中注意到的一个更改,该设计是错误的,不允许将所有可能的业务情况记录到没有该问题的设计。

“复合”与“简单”与“空”适用于 FK、PK、AK、CK(候选密钥)和超级密钥,并且与 FD 和 JD 部分相关。定义将在重要时指定复合/简单/空。(例如:有时 FD 被放入涉及单列的规范形式。有时我们可以很容易地部分基于 CK 是否简单来推断 NF 成立。)

获得表后,声明(足够的)约束。然后 DBMS 可以强制执行它们。FKs、PKs、AKs、CKs、superkeys、FDs & JDs 都有相关的约束。SQL 允许您声明所有 PK 和 AK(通过PRIMARY KEY& UNIQUE NOT NULL)。这些声明实际上声明了超级密钥,当其中没有声明较小的密钥时,它们恰好是 CKs/PKs/AKs。类似地,SQLFOREIGN KEY声明一个外部超键,如果它实际上是一个 CK,它就是一个 FK。声明足够的FKs 链以强制执行您未声明的链。(通过传递性。)SQL DBMS 通常不允许您声明 FK 循环。SQL 还让您声明声明所引用的超键,FK无论这些列是否包含较小的声明超键/CK,因此必须成为超级钥匙。通过触发器声明或强制执行任何 CK 约束未隐含的 FD 或 JD 约束。(5NF 摆脱了所有这些限制,除了 CK 上的一些 FD 循环。)

查找学术教科书定义和算法。

于 2017-07-13T05:56:37.567 回答