【问题标题】:Database Design related to Categories and Subcategories与类别和子类别相关的数据库设计
【发布时间】:2014-07-18 18:48:07
【问题描述】:

我对此进行了无止境的研究。我不是唯一一个问过这个问题的人......但我希望您能对最佳做法提出意见。

我正在尝试设计一个可以跟踪金融交易的数据库。为简单起见,每笔交易只能有一个Category,每个Category只能有一个Sub-category。

我有一个自引用表,如下所示:

Table:  Categories
ID, int, primary key
parentID, int, foreign key
description, text

长话短说,你最终会得到这样的数据:

1 Auto [null]
2 Bills [null]
3 Healthcare [null]
4 Maintenance 1
5 Gasoline 1
6 Cell Phone 2
7 Rent 2
8 Prescriptions 3
9 Dentist 3

到目前为止,一切都很好。 这是我的问题

我不知道我应该以正确的方式将这一切与我的交易表联系起来。 “交易”有一个“类别”和“子类别”列。 Transaction.ID 是 PK,Categories.ID 是 FK。

对于以上述方式与类别相关的事务,这意味着类别中的任何值都可以写入类别或子类别...

作为程序员,我有责任通过表单控制对表格的访问吗?换句话说,我唯一的选择是“以编程方式控制”类别和子类别列中的内容吗?

请记住,每个类别只能有一个子类别。所选类别应仅允许该类别的子级...

我说得有道理吗?

良好:自动 -- 维护 不好:医疗保健——汽油

【问题讨论】:

  • ...为什么只能有一个子类别?这是否意味着像Auto - Gasoline 这样的东西会被禁止?或者你的意思是你只想要一个嵌套级别? Transactions 应该只有一列 - category,它可能包含一个子类别。要么,要么定义一个多列外键。您预计如何加载数据?该程序/进程有责任首先不加载不良数据,因此在此处放置您需要的任何基本保护。
  • 你的意思是每个子类别只能有一个类别吗?
  • 目前,我不太关心层次结构有多深...每个子类别可能只有一个父级。这部分很简单......我的问题是限制写入 Transactions 表的内容。例如:如果我用“Auto”填充 Transactions.Category,我应该只能在到达 Transactions.SubCategory 时选择 Auto 的孩子。

标签: sql database-design ms-access-2010 database-schema


【解决方案1】:

您提出的案例是在关系表中编码分层数据、树结构的更一般问题的子集。自从关系数据库在 1970 年代后期首次出现以来,就已经对这个案例进行了非常详细的研究。

特别是在簿记系统中,每次都会出现子类别和类别的想法。较大规模的工业系统往往具有四级系统,包括总体账户类型(费用)、类别(运输)、子类别(汽车)和子子类别(汽油)。

如果您使用以下搜索词,您的研究可能会更有成效:“关系设计中的树结构”。该搜索产生了以下维基百科摘要:

http://en.wikipedia.org/wiki/Hierarchical_database_model

您可以在 SO 中找到很多相关的问题和答案。在“嵌套集”或“邻接列表”下搜索几种技术。

您的问题是将您找到的答案简化为只有两个级别的情况:类别和子类别。

我认为您选择的任何设计都希望明确以下规则:子类别决定类别。 IMO,您将希望 DBMS 强制执行此规则,以便没有事务以与其类别不一致的子类别结束。

【讨论】:

  • 我想我们是一致的! Transactions.SubCategory 必须与 Categories.Table 中的正确父级相匹配。编写代码是我的责任,还是我可以通过关系强制执行?我似乎无法建立适当的关系......到目前为止,我所做的最好的是分别显示 Transactions.Categories 和 Transactions.SubCategories 的所有类别和子类别。也就是说,我还没有找到基于 Transaction.Category 限制 Transaction.Subcategories 的方法。
  • 强制Subcategory/Category关系的一致性基本上是数据规范化的问题。规范化设计将只存储这种关系一次。研究标准化设计。至于数据输入表单如何向用户呈现选项,这是表单设计而不是数据库设计的问题。
【解决方案2】:

因此,您的分类不是正交和独立的(例如性别和城市),而是分层的(例如州和县)。

为了强制执行分层分类,请使用单个分类表,其中 ID 列作为主键,在数据表中作为外键引用,以及两个描述性字段 Category 和 Subcategory。

为了方便数据输入,您可以提供一个组合框类别来过滤可用的子类别。然而,实际的外键引用是由在 Subcategory 组合框中所做的选择提供的,它必须列出 Category 和 Subcategory 这两个字段。通常用破折号 (-) 或竖线 (|) 等分隔符连接这两个字段。

【讨论】:

  • 子类别的单个 FK 就足够了。子类别表可以有一个 FK 引用类别。因此,与 Gasoline 相关的所有交易都与 Auto 间接相关。
  • @WalterMitty:这假定子类别 description 始终是唯一的。考虑州和县的例子;美国 50 个州有许多重复的县名,因此只有在结合州描述时才能保证任何特定的县名。
  • 它假定子类别具有标识。没有身份的实体是个问题,即使其他一切都是正确的。
  • @WalterMitty:当然——我是这种设计方法的传播者。有时将类别简单地视为子类别的一个属性(当类别没有自己的属性时)更简单,我认为在这种情况下是正确的。
  • Walter & Pieter:我会以你们认为最好的任何方式设计包含类别和子类别的表格...为了更好地澄清:我的问题是限制写入事务表的内容.例如,如果我用“Auto”填充 Transactions.Category 记录,那么当我到达 Transactions.SubCategory 时,我应该只能选择 Auto 的子项。我有责任为客户编写代码吗?或者,这种关系是否可以在数据库本身内强制执行?
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 2011-02-17
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-20
  • 2013-12-17
  • 2021-12-12
相关资源
最近更新 更多