如何将此架构更改为3NF?

时间:2019-05-07 21:02:42

标签: sql oracle database-normalization

我创建了以下两个表,用于历史教室设置。这些表格将包含有关整个历史战争以及其中一部分国家的数据。

我的问题是Wars表中的Combatants字段不在3NF中,因为战争中可能有许多战斗人员(即国家)。

如何在不创建任何人工密钥的情况下将该模式更改为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);

1 个答案:

答案 0 :(得分:0)

您在这里拥有的是多对多关系,一场战争可以有多个国家,而一个国家可以参加多个战争。

要在您的模式中表示这一点:

1)从“战争”表中删除“战斗员”字段

2)创建一个“ NationsWars”表(或任何您想调用的表)。它只需要包含国家名称和战争名称。

3)这两个字段中的每一个都将具有一个外键,该外键返回其各自父表的主键。

4)此新表的主键将是由上述两个字段组成的复合键。

这是代表这种多对多关系的经典,标准方法。


我不确定为什么您在这里反对人工钥匙。我想说数字自动增量ID是国家和战争表的理想键...这样,如果一个国家更改了名称,或者您意识到自己输入了错字,或者您想重新标记战争,那么您可以这样做而不会违反任何关键约束。通常,将名称或描述字段用作键是一种不好的做法,因为从长远来看,它们几乎总是会发生变化。主键应该是可以唯一且永久地标识特定记录的东西,并且没有其他上下文意义。