我正在建立一个实验室数据库,分析来自不同地点的各种样本。某些位置需要与样本一起保留自己的参考编号(或其他属性)。
我应该如何表示仅适用于我的样本子集的列?
选项1:
为每个唯一的属性集创建一个单独的表?
SAMPLE_BOILER: sample_id (FK), tank_number, boiler_temp, lot_number
SAMPLE_ACID: sample_id (FK), vial_number
这个选项看起来太单调乏味,特别是随着系统的发展。
选项1a:类表继承(link):内部节点/表中具有公共字段的树
选项1b:具体表继承(link):叶子节点/表中具有公共字段的树
选项2:将适用于任何样本的每个属性放入SAMPLE
表中。
每个条目的大多数列很可能是NULL,但是所有字段都存储在一起。
选项3:为使用的每种Oracle数据类型创建_VALUE_
个表。
这个选项要复杂得多。获取样本的所有属性需要访问下面的所有表。但是,系统可以动态扩展,而不需要为每个新样本类型使用单独的表。
SAMPLE:
sample_id*
sample_template_id (FK)
SAMPLE_TEMPLATE:
sample_template_id*
version *
status
date_created
name
SAMPLE_ATTR_OF
sample_template_id* (FK)
sample_attribute_id* (FK)
SAMPLE_ATTRIBUTE:
sample_attribute_id*
name
description
SAMPLE_NUMBER:
sample_id* (FK)
sample_attribute_id (FK)
value
SAMPLE_DATE:
sample_id* (FK)
sample_attribute_id (FK)
value
选项4:(添加您自己的选项)
答案 0 :(得分:3)
为了帮助使用Google搜索,您的第三个选项看起来有点像Entity-Attribute-Value模式,虽然经常是discussed on StackOverflow before,但它通常是CouchDB。
正如其他人所建议的那样,如果可能的话(例如:一旦系统启动并运行,几乎没有新属性出现),您应该以传统方式使用关系数据库,将表作为类型和列作为属性 - 您的选项1.随着数据库按照设计的方式工作,初始设置难度将值得。
另一件需要考虑的事情是:你是否与甲骨文相关联?如果没有,那里有非关系数据库,如{{3}},它们不受关系数据库所用的前端模式约束。
编辑:您已经询问过如何处理选项1下的新属性(问题中现在是1a和1b)...
如果选项1是一个合适的解决方案,那么很少有新属性可以接受改变数据库模式以适应它们的开销,所以......
您将编写数据库脚本来更改表和添加列,因此可以在这些脚本中轻松处理默认值的提供。
在两个1选项(1a,1b)中,我个人的偏好是具体的表继承(1b):
虽然这些第一选项中的任何一个都是比其他选项更好的解决方案,但如果这是您更喜欢的类表继承方法没有任何问题。
这一切都取决于真正出现新属性的频率。
如果答案是“很少”,那么偶尔的架构更新可以应付。
如果答案是“很多”,那么关系数据库模型(具有固定模式烘焙)不是最佳工具,因此包含它的解决方案(entity-attribute-value, XML列等等总是显得有点费力。
祝你好运,让我们知道你是如何解决这个问题的 - 这是人们遇到的一个常见问题。
答案 1 :(得分:1)
选项1 ,但它不是每组属性的单独表格:为每个样本源创建一个单独的表。
即。从您的例子中:锅炉的样品将有罐号,锅炉温度,批号;酸样品有样品瓶号。
你说这很乏味;但我建议你现在收集和编码数据意义的工作量越多,以后会产生巨大的回报 - 从长远来看,你会节省成本,因为你的报告更易于编写,理解和维护。那些来自锅炉房的人会问“我们需要知道按照这套锅炉温度范围分组的罐子总数”,你会说“没有问题,给我半个小时”,因为你已经做了很多努力码已经。
选项2 将是我的后备选项,如果选项1证明是过度杀伤。您仍然希望分析需要哪些字段,它们的数据类型和约束是什么。
选项4 是使用选项1和2的组合。您可能会发现许多样本类型之间共享了一些属性,并且这些属性可能有意义样本表;而其他属性对某些样本类型非常具体。
答案 2 :(得分:1)
你应该选择使用选项1.尽管创建起来比较繁琐,但在尝试查询数据时,选项2和3会让你感到厌烦。查询将变得更加复杂。
事实上,存储数据最重要的部分是查询它。您还没有提到计划如何使用数据,这是数据库设计中的一个重要因素。 据我所知,第一个选项最容易查询。如果您打算使用报告工具或ORM,他们也会更喜欢它,因此您可以保持您的选择。
事实上,如果您发现构建表格繁琐,请尝试从一开始就使用ORM。好的ORM将帮助您从一开始就创建表。
答案 3 :(得分:0)
我会根据您通常看到数据的方式做出决定。例如,如果您每天获得5-6个新属性,那么您将无法继续添加新列。在这种情况下,您应该为“标准”属性创建列,并添加类似于“选项3”的键/值布局。
如果您不希望看到这一点,我现在就选择选项1,并且只有当您的设计变得过多时,才会将您的设计修改为“选项3”。最终可能会在最初几周内添加25个属性,而在几个月内则没有任何属性。在这种情况下,你会很高兴你没有做额外的工作。
对于选项2,我通常建议不要这样,因为关系数据库中的Null意味着值为“未知”,而不是“不适用于”特定记录。虽然我在过去与我一般都尊重的人不同意这一点,所以我不会对它发起任何战争。
答案 4 :(得分:0)
无论你做什么,选项3都很糟糕,每个查询都会加入数据来创建一个SAMPLE。 听起来你有一些通用的SAMPLE字段需要与样本类型的更具体数据连接。您是否考虑了一些user_defined字段。
实施例:
SAMPLE_BASE: sample_id(PK), version, status, date_create, name, userdata1, userdata2, userdata3
SAMPLE_BOILER: sample_id (FK), tank_number, boiler_temp, lot_number
答案 5 :(得分:0)
如果样本属性集是相对静态的,那么从长远来看使您的生活更轻松的实用解决方案将是选项#2 - 这些都是SAMPLE的所有属性所以它们应该全部在同一张桌子里。
好的 - 你可以将基本属性的一个漂亮的对象层次结构与各种扩展组合在一起,但它会比它的价值更麻烦。把事情简单化。您总是可以将样本属性子集的几个视图放在一起。
如果样本属性列表非常动态,并且您需要用户能够创建自己的字段,我只会选择#3选项的变体。
在实施动态用户定义字段方面,您可能首先想要阅读Tom Kyte对this question的评论。现在,汤姆可以非常坚持他的观点,但我从他的评论中得知,你必须非常确保你真正需要灵活性让你的用户在你做之前动态添加字段它。如果你真的需要这样做,那就不要为每种数据类型创建一个表 - 这太过分了 - 只是以标准方式将所有内容存储在varchar2中,并用适当的数据类型标记每个属性。
create table sample (
sample_id integer,
name varchar2(120 char),
constraint pk_sample primary key (sample_id)
);
create table attribute (
attribute_id integer,
name varchar2(120 char) not null,
data_type varchar2(30 char) not null,
constraint pk_attribute primary key (attribute_id)
);
create table sample_attribute (
sample_id integer,
attribute_id integer,
value varchar2(4000 char),
constraint pk_sample_attribute primary key (sample_id, attribute_id)
);
现在......只是看起来很邪恶不是吗?你真的想去那里吗?
答案 6 :(得分:0)
这可能是一个愚蠢的问题,但您需要对属性值做些什么?如果您只需要显示数据,那么只需将它们存储在一个字段中,可能是XML格式或某种序列化格式。
您始终可以使用模板表来定义样本“类型”以及为数据输入表单显示的可用字段。
如果你需要对它们进行过滤,唯一有效的模型就是选项2.正如其他人都说的那样,选项3的实体 - 属性 - 值样式在某种程度上是精神上的,并且没有真正的乐趣。我过去自己尝试过,一旦实施,我希望我没有打扰过。
尝试围绕用户与其进行交互的方式(以及如何查询)来设计数据库,而不仅仅是对数据进行建模。
答案 7 :(得分:0)
我在商业和自制系统上工作,用户可以动态创建自己的字段/控件。这是它的工作原理的简化版本。
表:
页面只是一个或多个控件的容器。它可以命名。
控件链接到页面并表示用户输入控件。 控件包含它的数据类型(int,string等)以及它应如何表示给用户(文本框,下拉列表,复选框等)。
值是用户在控件中键入的实际数据,一个值包含一个列,表示它可以表示的每种数据类型(int,string等),并且根据控件类型,相关列设置为用户输入。
值中有一个附加列,用于指定值所属的组。 每次用户填写控件形式并单击保存时,控件中输入的值将保存到同一组中,以便我们知道它们属于一起(增量计数器)。
答案 8 :(得分:0)
CodeSpeaker, 我喜欢你回答,它指出了我正确的方向来解决类似的问题。 但是你如何处理下拉列表值呢? 我正在考虑一个值的Lookup表,以便许多查找链接到一个UserDefinedField。 但是我还有另外一个问题需要添加到混音中。每个字段必须具有多个链接语言,因此每个值必须链接到多种语言的等效值。 也许我正在考虑这个问题,因为到目前为止我已经有了6张桌子。