规范化数据库有什么好处?

时间:2016-09-28 17:00:34

标签: java database-design relational-database entity-relationship

我真的无法对此有充分的理解。我在互联网上看到很多例子,但缺乏对原因的解释。例如,您在应用程序中有两种用户,即客户和经理。创建单独的“user_type”表而不是在用户表中合并“user_type”列有什么好处。另一个示例是为产品类别创建单独的表,而不是将类别字段放在产品表中。我真的无法理解这一点。 db规范化有哪些优点?以及数据库中重复数据的缺点?

2 个答案:

答案 0 :(得分:1)

重复数据的缺点是您必须记住数据的所有副本的位置,并在信息更改时更新所有数据副本。规范化更多是关于重复数据删除而不是创建单独的表。

在user_type的示例中,您可以将其放在用户表的列中。如果用户可以拥有多个用户类型,则附加表会派上用场。

答案 1 :(得分:0)

规范化的目的是防止异常数据进入数据库。

例如,采用一个非常简单的用户实体:

create table Users(
  ID        int auto_generated primary key,
  LastName  varchar( 16 ) not null,
  FirstName varchar( 16 ) not null
);

现在结果可以有两种类型的用户:Manager(M)或Peon(P)。此外,对于管理人员,我们需要知道有多少人直接向他们报告,对于peons,我们需要知道他们是否拥有叉车许可证。让我们把它扔到桌子上:

create table Users(
  ID           int auto_generated primary key,
  LastName     varchar( 16 ) not null,
  FirstName    varchar( 16 ) not null,
  UserType     char( 1 ) not null,
  DirectReps   int,
  HasFLLicense boolean
);

这应该会启动各种警报。什么可能出错?

  • UserType的唯一有效值(此时)是' M'或者' P'。但是,该字段可以包含任何单个字符。我们可以创建一个" check"在这个专栏中,但这将产生另一个问题,我将在稍后介绍。
  • DirectReps和HasFLLicense字段仅适用于UserType字段包含' M'或者' P'分别。没有办法在内部强制执行此操作 - 必须使用触发器和/或应用程序代码。

没有简单的方法来强制执行这些新约束。而且我们都知道,无论我们多么小心,我们迟早会有UserType值而不是' M'或者' P'和/或DirectReps或​​HasFLLicense中的值不恰当。这是异常数据。

如果仔细观察,LastName,FirstName和UserType字段仅对ID具有功能依赖性。但是,DirectReps和HasFLLicense也依赖于UserType。这个新表不在2nf。

规范化这个表可以通过几种不同的方式完成,所以我不会进入。 (Here是我今天早些时候提出的一种方法。)不用说,最终结果应该是这样的,除非UserType值是' M'否则不能存在DirectReps值。除非UserType值为' P'

,否则不能存在HasFLLicense值。

现在让我们看看规范化的表:

create table Users(
  ID           int auto_generated primary key,
  LastName     varchar( 16 ) not null,
  FirstName    varchar( 16 ) not null,
  UserType     char( 1 ) check( UserType in( 'M', 'P' )
);

有一些规范化方法也会从表中删除UserType字段,但现在让它留在这里。无论位于何处,以下内容均适用。

当您考虑迟早需要第三种类型时,会出现问题。在不同的点,另一个,然后另一个,你得到的想法。每次我们必须发出alter table命令只是为了重写检查约束。这就像完全拆除和重建你的家只是为了更换你的客厅沙发。访问此表的所有代码(包括视图)必须至少重新编译并可能被重写。让我们面对它,alter table是一项非常重要的操作。

查找表包含每个用户类型的记录要好多少:

create table UserTypes(
  ID      char( 1 ) not null primary key, -- 'M' or 'P' or whatever
  Name    varchar( 16 ) not null,  -- "Manager" or "Peon" or whatever
  ...     -- other possible attributes
);

然后可以定义UserType字段:

  UserType     char( 1 ) not null references UserTypes( ID )

现在添加一个类型' A'或者' F'或者只是将记录插入UserTypes表的问题。现有代码不受影响。当然,最终必须更改应用程序代码以处理新类型,但应用程序开发人员现在可以在闲暇时执行此操作。

不要只针对当前的要求进行设计。同时设计合理预期的未来要求。