数据库规范化:使用单独的表来存储单个字段

时间:2012-03-11 18:25:15

标签: mysql database normalization

目前我们的数据库已设置好,以便付款交易记录付款类型ID,并链接到包含这些值的付款类型(现金,支票,信用)表。例如:

  

付款交易

     
      
  • ID
  •   
  • 金额
  •   
  • 日期
  •   
  • 付款类型ID
  •   
     

付款方式:

     
      
  • ID
  •   
  • 付款方式(现金,信用)
  •   

我的问题是,我是否应该删除付款类型表,并将付款类型值作为文本存储在付款交易中。

这类似于this question。除了支付类型之外,很可能确定每种支付类型都不需要添加新信息。 “现金”与任何东西都没有联系,关于现金本身我无需了解,只是。

据我所知,用一个字段替换付款方式表的优缺点是:

赞成

  • 每当需要找到付款类型时,删除大部分不必要的加入。
  • 交易的付款类型将始终准确反映交易记录时的情况。即如果我将支付类型表中的“现金”记录更改为“信用”(无论出于何种原因),则链接到现金的所有支付交易现在都将链接到信用卡。

缺点

  • 将付款类型存储为文本字段会降低按付款类型排序的速度,并使这种类型比现在更麻烦。
  • 交易的付款类型将始终准确反映交易记录时的情况。即如果我输入错字并且付款类型存储为“Kash”,我可以轻松修复该错字,并且所有链接到该付款类型的交易都将自动更新。

我倾向于删除付款类型表并将单个字段添加到付款交易表中,您建议哪种方式是最佳方案?

2 个答案:

答案 0 :(得分:2)

我不同意你的任何一个专业论点。

  

每当付款类型需要时,删除大部分不必要的联接   被发现。

您只是假设这将成为性能瓶颈。当您拥有必须使用的数据时,应该执行非规范化。这不是其中之一。

  

交易的付款类型将始终准确反映出什么   这是在记录交易时。即如果我改变了   付款类型表中的“现金”记录为“信用”(无论如何)   原因),现在将链接到现金的所有支付交易   信用。

您不应该允许某人以这种方式修改付款方式。更改付款类型应该是另一个具有自己时间戳的交易。

任何关系数据库都可以处理JOIN和规范化表。我担心你会过早优化。

我花更少的时间担心这个问题,花更多的时间思考如何处理历史问题。在将事务移到历史表之前,您将保留多长时间?您是否考虑过根据时间戳将数据库按月分区?那将更值得你的努力。

答案 1 :(得分:1)

如果删除PaymentType表,则使用表CHECK约束替换外键检查:

PaymentType   CHAR(6) NOT NULL CHECK(PaymentType IN('Cash', 'Credit', 'Cheque')

好的 - 你把'check'写成'check';只是英语和美国人之间的另一个区别。

现在,这使得找出可能的值更加困难;你必须分析系统目录才能找到答案。使用单独的表,您可以检查单独的表以找出允许的内容。假设您开始跟'信用'分开跟踪'借记';您向表中添加一行,与表模式更改相对应。假设您决定需要记录未来交易中允许的代码(因此“现金”不再是一种选择)。您可以在“付款方式”表中添加一列,以指示此代码不再有效;使用简单的CHECK约束很难做到这一点。

因此,即使您目前在付款方式表中有额外数据有限或没有额外数据,我也会使用付款方式表,而不是在付款交易表中嵌入付款类型。

如果是我的设计,我可能会使用CHAR(1)或CHAR(2)代码作为支付类型的标识符,而不是数字列。当然,所有三种类型都以'C'开头,所以也许你可以使用'A'代表cAsh,'H'代表cHeck,'R'代表cRedit(也可以代表'D'或'E'代表借记或dEbit)用CHAR(1)代码;使用CHAR(2),你可以使用'CA','CH','CR'(也许是'DE')。全名可以存储在付款类型表中,以便在报告中使用。在这种情况下,好处不是很大,但是在足够的记录上保存每个记录4个字节(足够多的足够小的记录),它可能成为您的存储成本的一个因素。当然,指数开销也会发挥作用;如果必须对付款交易表中的列编制索引,则较小的字段使用较少的索引空间。