【发布时间】:2019-05-08 05:20:44
【问题描述】:
我创建了以下两个表格,用于历史教室环境。这些表格将包含有关历史上的战争以及参与其中的国家的数据。
我的问题是 Wars 表不在 3NF 中,因为 Combatants 字段中有多个值,因为战争中可能有许多战斗人员(即国家)。
如何在不创建任何人工键的情况下将此架构更改为 3NF(即仅使用我当前拥有的字段)?
CREATE TABLE Wars (
Name CHAR(50) PRIMARY KEY,
StartingDate DATE NOT NULL,
EndingDate DATE NOT NULL,
Cause CHAR(50) NOT NULL,
Combatants CHAR(50) NOT NULL,
TodaysDate DATE DEFAULT SYSDATE,
CONSTRAINT CHK_TD CHECK(EndingDate < TodaysDate),
CONSTRAINT CHK_SD CHECK(StartingDate > 0);
CREATE TABLE Nations (
Name CHAR(50) PRIMARY KEY,
StartingDate DATE NOT NULL,
EndingDate DATE,
TodaysDate DATE DEFAULT SYSDATE,
CONSTRAINT CHK_TD CHECK(EndingDate < TodaysDate);
【问题讨论】:
-
每个战斗员是否也与一个国家(甚至国家)有关联?
-
是的,每个战斗员都是一个国家。
-
哦,我明白你的意思是“战斗人员”是国家,而不是人或其他任何东西。它有助于在整个架构中以相同的方式命名相同的实体!那么我假设每个国家也可以出现在不止一场战争中?如果是这样,那么您需要实现多对多关系,并使用第三个表表示该关系。
-
顺便说一句,您对这里的人工密钥有什么反对意见?我会说数字 ID 将是国家和战争表的理想键......这样,如果一个国家改变了它的名字,或者你意识到你打错了,或者你想重新标记一场战争,那么你可以这样做所以不违反任何关键约束。使用名称或描述字段作为键通常被认为是不好的做法,因为从长远来看,它们几乎总是会发生变化
-
我在下面写了一个正式的答案。如果对您有帮助,请记得将其标记为已接受 - 谢谢!附言纯粹从学术角度来说,如果所有战争的起因都可以用一个 50 个字的领域来概括,而不是无穷无尽的书籍和论文的主题,那该多好啊! :-)
标签: sql oracle database-normalization