【发布时间】:2018-01-30 23:13:42
【问题描述】:
我来这里是为了提出一个问题,我在过去几天开发数据库设计时一直在努力解决这个问题。
简介:
该数据库旨在存储有关电机类型的信息(不是关于实际电机,而是更多关于它们的设计、参数等)、它们的组件/属性以及某些电机类型之间的关系(每个电机类型都与所谓的基本电机类型相关)。所以我们有几个motortypes,每个都有许多属性(我称之为detailtypes)。每个细节类型依次可以出现在一个或多个电机类型中。每个 motortype:detailtype 组合应该(完全)有一个值。
我需要能够比较两种不同电机类型的特定详细信息类型的值,并根据此比较存储信息。 (此信息的存储是数据库的中心目的。)
现在第一个也是最简单的方法是制作一个 motortype 表并使其每个 detailtype 都有一个列,这样我就可以为每个组合存储一个值:
Approach #1:
CREATE TABLE Motortype(
id INTEGER PRIMARY KEY,
description CHAR (50),
detailtype1 CHAR (50),
detailtype2 INTEGER,
detailtype3 YES/NO,
detailtype4 DOUBLE );
将有大约一百个(这个数字在未来可能会缓慢增长)这样的详细信息类型要输入到数据库中。添加更多对应于添加更多列(可管理),更改它们会导致重命名列(坏主意?)。当我想将电机类型与 ID 2 和 5 的 detailtype2 值进行比较并保存有关此比较的信息时,就会出现问题。我不知道如何管理它。 (此外,属性不能有 NOT NULL 约束,因为某些数据在创建条目时可能只是未知的......)
这就是我继续接近 2 的原因,它似乎以某种方式实现了 EAV。
为了允许存储比较信息,我将 detailtypes 从一个属性移到了 mototype 到它们自己的实体,同时将不需要比较的那些作为属性:
Approach #2:
CREATE TABLE Motortype(
id INTEGER PRIMARY KEY,
description CHAR (50),
notComparableAttribute1 CHAR (50),
notComparableAttribute2 INTEGER
);
CREATE TABLE Detailtype(
id INTEGER PRIMARY KEY,
description CHAR (50),
datatype CHAR (3)
);
CREATE TABLE MotorDetail(
id INTEGER PRIMARY KEY,
motortype_id INTEGER CONSTRAINT fk_mt_id REFERENCES Motortype(id) NOT NULL,
detailtype_id INTEGER CONSTRAINT fk_dt_id REFERENCES Detailtype(id) NOT NULL,
value CHAR (50) NOT NULL
);
然后,此配置允许我引用 MotorDetail 中的任何特定值对并保存用于此比较的附加信息。 (请注意,此比较有更多维度 - 它与 MotorDetail 没有 1:1 关系。而是 1:n MotorDetail:ComparisonData 关系。否则我可以直接将所有比较信息存储在 MotorDetail 中。)
但是,我现在有一个 value 属性需要保存几种不同的数据类型(字符串、整数、浮点数、布尔值),这意味着输入验证的责任从数据库转移到了我身上(我需要确保用户只能以对相应 Detailtype 有意义的方式输入数据)。这完全没问题 - 只是增加了一点编程工作,但我觉得可以用更优雅的方式解决它。
所以在对多态关联进行了一些研究之后,我想出了下一个方法(Motortype 和 Detailtype 与 #2 相同):
Approach #3:
CREATE TABLE MotorDetail(
id INTEGER PRIMARY KEY,
motortype_id INTEGER CONSTRAINT fk_mt_id REFERENCES Motortype(id) NOT NULL,
detailtype_id INTEGER CONSTRAINT fk_dt_id REFERENCES Detailtype(id) NOT NULL,
valueTxt CHAR (50),
valueInt INTEGER,
valueDbl DOUBLE,
valueBoo YES/NO
);
值属性不能有 NOT NULL 约束,因为 75% 的值将为空(根据要求,每个 MotorDetail 只能有一个值)。只要我只需要特定数据类型的值,查询值似乎就可以了,否则它会变得更加复杂(例如,在表单上显示它们)。或者我应该说乏味而不是复杂。
所以在最后一次尝试解决这个问题时,我提出了我的最终方法(再次,Motortype 和 Detailtype,如 #2 所示):
Approach #4:
CREATE TABLE MotorDetail(
id INTEGER PRIMARY KEY,
motortype_id INTEGER CONSTRAINT fk_mt_id REFERENCES Motortype(id) NOT NULL,
detailtype_id INTEGER CONSTRAINT fk_dt_id REFERENCES Detailtype(id) NOT NULL
);
CREATE TABLE MotorDetailValueTxt(
id INTEGER PRIMARY KEY,
valueTxt CHAR (50)
);
CREATE TABLE MotorDetailValueInt(
id INTEGER PRIMARY KEY,
valueTxt INTEGER
);
... (same for MotorDetailValueDbl and MotorDetailValueBoo)
我不确定这个。不确定如何表示值表中的每个 id 都与一个 MotorDetail(id) 相关联,并且需要在 所有 值表中是唯一的。甚至不确定我是否完全理解了基本概念。但我可以肯定的是,这样做数据库不能强制引用完整性。这就是我不打算使用它的原因。在一个测试数据库中,我能够使用 UNION 生成一个查询以获取所有不同的值,但我认为我不想在表条目级别进行任何内务管理(以某种方式确保没有死条目)。
问题:
鉴于到目前为止概述的详细信息,是否存在不涉及某种编码魔法(VBA 或其他)的可能解决方案?一个优雅的解决方案,以某种方式允许在数据库级别处理这一切(表+关系,而不是报告、表单等......)?到目前为止,我提出的所有内容都显得相当笨拙。
注意:我是数据库设计和一般数据库的新手。我在 MS Access 中接受了 3 天的培训,但这主要是针对学习 GUI 和构建一些非常基本的数据库而量身定制的。关于我知道(或假设知道)有关数据库开发的任何其他内容,都是通过阅读博客了解到的 - 最重要的是:SO 上的问题和答案。
可以假设我没有(完全)理解我讨论的一个或多个概念,因此歪曲了其中的一些概念,这似乎是安全的。如果是这样,或者如果缺少其他任何内容,请在 cmets 中向我指出或进行编辑以改进我的问题(并允许我阅读它)。 :)
编辑:进行了编辑,并且进行了很大的编辑。我试图添加信息,澄清那里的内容,并仍然保留问题的原始特征和意图。让我们希望我至少部分成功了。 :)
【问题讨论】:
-
@philipxy 感谢您的评论。阅读有关子类型/多态性是导致这个问题的原因。我目前正在阅读“FKs to multiple/two/many tables”。我当然不打算使用 EAV,也许我的带有示例值的表是以令人困惑的方式编写的?我将尝试在编辑中澄清这一点。我确实有几本关于数据库设计的书,但是它们没有提到更复杂的关系(它们可能过于面向初学者)。实际上,我确实从一个非常简单的设计开始,但由于业务需求,它很快变得相当复杂。
-
@philipxy 关于“有问题的文本,不在链接/图像中”:这不是我的做法吗?唯一符合“在链接/图像中”的文本是图像“标题”中的文本(由于我还不允许发布内联图像)以及屏幕截图中的文本。我不确定你在这里的意思。并重新“使用代码格式格式化表格”:我做到了。我的问题中唯一的表格被格式化为代码。还是说我应该将链接图像中的关系呈现为 ASCII 艺术?
-
我想我现在明白你对 EAV 的看法了。 :( 但我不确定以不同的方式进行操作实际上是否可行。如前所述,每个电机有大约 100 个详细信息。这将导致创建一个巨大的表(100 列)或大约 100 个带有巨大链接表的表在电机表和细节表之间。但无论如何我认为我需要回去重新评估我的模型。
-
您的图片是 DDL 的图片。 Give the DDL. 无论如何你都应该这样做--minimal reproducible example。我不建议 EAV;只是一列在 EAV 中给出了另一列的类型——其中数据对于表示是必不可少的——在某些子类型习语中——作为冗余的变体标签并用于约束。重新设计一个初始设计,忘记“巨大”,找到简单的关系(船)/关联。稍后重新排列。记住——DBMS 已经有元数据和 DDL 命令。
-
我怀疑您的问题比您的问题更简单和基本。同样,它的设计是一些尚未给出的简单设计的复杂版本。 (当然你可以给出一个与实际平行的简单例子?)然后是我们的问题,考虑到(组合)问题什么是合理的权衡和习语。关于我的最后一条评论,阅读使用“(数据库或 sql)子类型”、“许多空列或许多表”、“多个表的外键”和“EAV”的谷歌搜索“stackoverflow”的第一页命中。 (重新 EAV stackoverflow.com/a/23950836/3404097 和 stackoverflow.com/a/33557166/3404097)。祝你好运。
标签: ms-access database-design relational-database polymorphic-associations