我正在开发一个数据库。我很感激帮助重组2到3个表,所以数据库都符合前3个普通表格;并且实用,并在未来扩展/增加。我现在想花时间减少努力/混淆。
PREAMBLE
请注意,虽然我有一定的经验和技巧,并且充满热情,但我既是一个笨蛋又是一个业余爱好者!
项目背景
我正在编写一个小型(虽然雄心勃勃!)Web应用程序(使用PHP和AJAX到 MySQL 数据库)。它本质上是一个库存管理系统,用于记录和查看每个设备的当前位置及其维护历史。如果相关,交易将非常低(每天可能少于100,但可能同时连接/操作)。行数也将非常低(可能是几千)。
它将处理许多完全不同类别的设备,例如自行车和灯具(随机举例)。每个设备单元的详细信息或规格都记录在数据库中。对于自行车,重要的规格可能是框架颜色,而灯可能需要有关灯罩材料的信息。
由于类别的设备非常一点点,我认为存储信息的最合理方式是每个类别1个表 。这样,每个类别都可以包含特定于该类别的列。
我打算在单独的表中存储类别列表。每个类别都有一个该类别唯一的ID。 (根据最终设计,这可以作为查找表和/或作为运行查询的表。)可能只有很少的类别(可能是10到20),除非系统特别成功并且扩展
自行车列表将保存在自行车表中。 每辆自行车都具有该自行车独有的id(例如自行车0001)。 但灯表中存在相同的id(即灯0001)。
通过我的应用程序,我希望用户(从下拉列表中)选择类别类型(例如自行车)。 然后,他们将输入对象的数字ID(例如0001)。 这两个ID的组合足以唯一地标识对象。
图片:
当前的表格设计
建议的附加表
问题
我的直觉是,应该有一个“总体表”,它涵盖了每一件设备,无论它来自哪个类别。这比查询要简单得多,因为上帝知道有多少迷你桌子。但是当我尝试构建它时,它似乎会破坏各种正常形式。例如,引入冗余,不一致的可能性,引用完整性问题等。它也开始看起来像域表。
也许总体表应该是查询或视图而不是实体?
请您查看屏幕截图并告诉我您的意见。感谢。
出于各种原因,如果可能的话,我更愿意使用代理键而不是自然键。理想情况下,我更愿意在单列中使用该代理键。
目前,自行车(或灯)表仅使用第一列作为其主键。我是否应该将其扩展为包含Equipment_Category_ID
列的复合键?然后将Equipment_Article
表放入连接这两列的视图中(迭代地为每个设备类别)。可选的Bike_ID
和Lamp_ID
列可以重命名为通用内容,例如Equipment_Article_ID
。这可能会使查询更简单,但是存在丢失特异性的风险吗?它/ /仍然可以通过表名来限定。
说到冗余,当前灯或自行车表中的Equipment_Category_ID
似乎有点多余(如果该表中的每个项目/行在该列中具有相同的值)。< / p>
这一切仍然听起来很乱!但这肯定是非常普遍的问题,例如在线电子商店,租赁店等。希望有人会说那个老板栗!手指交叉!很抱歉没有简明扼要,但我无法解决遗漏的问题。如果有点健谈,大多数似乎都很相关。提前致谢。
更新日期27/03/2014 (回复@ElliotSchmelliot)
嗨,艾略特 感谢您的回复,并指出我正确的方向。我研究了OOP(用Java),但是没有意识到SQL中可能存在类似的东西。我阅读了您感兴趣的链接,其余的网站/图书看起来都是一个很好的资源。
MySQL InnoDB支持专业化吗?概括吗
不幸的是,经过3个小时的搜索和阅读,我仍然无法找到这个问题的答案。关键词I&m搜索包括:MySQL +(继承| EER |特化|概括|父|子|类|子类)。我找到的唯一积极结果是:http://en.wikipedia.org/wiki/Enhanced_entity%E2%80%93relationship_model。它提到了MySQL Workbench。
Equipment_Category可能的冗余(表3)
是和否。因为这是一个查找表,所以它目前有一个功能。 然而因为Lamp
或Bike
表中的每个项目属于同一类别,所以列本身可能是多余的;如果是,则Equipment_Category
表可能是多余的......除非在其他地方需要。我有打算将它用作webform下拉列表的RowSource / OptionList。将Equipment_Category作为建议的Equipment
父表中的列也不方便。如果没有它,如何为Lamp类别返回所有Equipment_Name
的列表(暂时忽略不同)。
实施
我无法知道将来可能需要添加哪些新类别的设备,所以我必须将超类/父级中包含的属性限制为我100%确定将对所有人共同的属性(或允许空值我假设);在许多子表中牺牲重复,以增加灵活性,并且从长远来看,希望更简单的维护。这一点非常重要,因为我们不会为此项目提供专业的IT支持。
变更确实必须实现自动化。所以我喜欢存储过程的想法。并且CreateBike
示例在Java中创建类的实例时听起来很熟悉(原则上,如果不是在语法中)。
有很多想法和自学的东西!如果您有任何其他意见,建议等,他们是最受欢迎的。而且,你能告诉我你用来创建UML图的软件吗?它的造型比我使用过的要好得多。
干杯!
答案 0 :(得分:1)
你对这个项目非常感兴趣,总是很棒!
我对您的数据库架构有一些建议:
每个设备实体都有单独的表格,即自行车或灯具。然而,您还有一个Equipment_Category表,纯粹用于将Bike表中的行标识为Bike或Lamp表中的行作为Lamp。这看起来有点多余。我假设Bike表中的每一行数据都代表一个Bike,那为什么还要打扰类别表呢?
你提到你的&#34;肠道&#34;感觉告诉你去寻找所有设备的总体表。您是否熟悉数据库设计中generalization and specialization的实践?你在这里寻找的是专业化(也称为#34;自上而下&#34;。)我认为拥有一个总体或者父母是一个好主意&#34;代表设备的表。然后,每个子实体,如Bike或Lamp将成为Equipment的子表。父表只包含所有子表共享的字段。
考虑到这些建议,以下是我可能会改变您的架构的方法:
在上面的架构中,一切都以设备开始。但是,每个设备都可以专门用于灯,自行车等。设备实体具有所有常见字段。 Lamp和Bike每个都有自己类型的字段。创建实体时,首先创建设备,然后创建专用实体。例如,假设我们正在添加&#34; BMX 200 Ultra&#34;自行车。我们首先在Equipment表中创建一个带有通用信息的记录(equipmentName,dateOfPurchase等)然后我们创建专用记录,在这种情况下是一个自行车记录,带有任何额外的自行车专用字段(wheelType,frameColor等)。创建专门的实体,我们需要确保将它们链接回父级。这就是Lamp和Bike实体都有一个设备ID的外键的原因。
添加专用实体的一种简单有效的方法是创建存储过程。例如,假设我们有一个名为CreateBike的存储过程,它接受参数bikeName,dateOfPurchase,wheelType和frameColor。存储过程知道我们正在创建一个Bike,因此可以轻松创建设备记录,插入通用设备数据,创建自行车记录,插入专门的自行车数据,以及维护外键关系。
使用专业化将使您的交易生活变得非常简单。例如,如果您想在2014年1月1日之前购买所有设备,则不需要加入。如果你想要所有带有蓝色frameColor的自行车,则不需要连接。如果您想要所有由毛毡制成的灯具,则不需要连接。如果您需要来自父实体和专用实体的数据,那么您需要将专用表连接回Equipment表的唯一时间。例如,显示所有使用100瓦灯泡并命名为#34;超级灯的灯。&#34;
希望这有帮助,祝你好运!
修改强>
如您提供的源中所述,专业化和泛化是增强实体关系(EER)的一部分,它有助于为您的架构定义概念数据模型。因此,它不需要被支持&#34;不过,它更像是一种设计技巧。因此,只要设计人员实现了它,任何数据库模式自然都支持特化和泛化。
就你的Equipment_Category表而言,我看到你来自哪里。确实可以轻松下载所有类别。但是,您可以简单地使用静态表(仅包含表示每个类别的字符串)来帮助这些填充,并且仍然将您的设备表分开。你提到只有大约10-20个类别,所以我认为没有理由在Equipment和Equipment_Category之间建立一座桥梁。连接越少越好。另一种选择是包括一个&#34; equipmentCategory&#34;设备表中的字段,而不是为它的整个表。然后,您可以简单地查询所有唯一的设备类别值。
我同意您希望将您的设备表保持在所有孩子之间的保证共同值。当然。如果事情变得太复杂而且您需要更多定义的实体,那么您可以随时将实体重新打破。例如,可能有一半的Bike实体是RoadBikes而另一半是MountainBikes。您可以随时继续专业化细分,以更好地了解这些独特的领域。
存储过程非常适合自动执行常见查询。最重要的是,参数化为SQL注入等安全威胁提供了额外的防御。
我使用SQL Server。我创建的图表直接来自SQL Server Management Studio(SSMS)。您只需展开数据库,右键单击Database Diagrams文件夹,然后使用所选表创建一个新图表。 SSMS为您完成剩下的工作。如果您无法访问SSMS,我可能会建议您尝试使用Microsoft Visio,或者如果您可以访问它,请使用Visual Paradigm。