【发布时间】:2013-08-08 23:06:32
【问题描述】:
我想使用实体-属性-值 (EAV) 方法创建患者/样本元数据表。
问题:我应该如何根据属性处理值的不同列类型(例如字符串、数字或字典表的外键) ?
注意:我不是在问是否使用 EAV 方法。我看过 other SO questions 和 references 并相信这是我用例的最佳方法(例如,我不想为每个 attribute 创建单独的列或表 - 这可以数以百计)。但是,如果给出一个综合示例,我肯定会重新考虑其他设计。
代表性数据
一个患者/样本(实体)可以有多个元数据属性(例如实验室位置、存活率、肿瘤类型),每个都有不同的值 类型(例如分别为VARCHAR、NUMBER、FOREIGN_KEY*)。
*FOREIGN_KEY 表示此 value 类型是 values 字典表的外键 ID (INTEGER)(例如 10 个可能的列表肿瘤类型)。所以实验室位置可以是VARCHAR,因为我不关心这些值的标准化。但肿瘤类型应该有一定程度的验证。
我的表格布局可能如下所示:
CREATE TABLE patients (
patient_id INTEGER CONSTRAINT pk_patients PRIMARY KEY,
patient_name VARCHAR2(50) NOT NULL
);
CREATE TABLE metadata_attributes (
attribute_id INTEGER CONSTRAINT pk_metadata_attributes PRIMARY KEY,
attribute_name VARCHAR2(50) NOT NULL,
attribute_value_type VARCHAR(50) NOT NULL -- e.g. VARCHAR, NUMBER, or ID
);
CREATE TABLE patient_metadata (
patient_id CONSTRAINT fk_pm_patients REFERENCES patients(patient_id) NOT NULL,
attribute_id CONSTRAINT fk_pm_attributes REFERENCES metadata_attributes(attribute_id) NOT NULL,
attribute_value ???
);
我认为在 metadata_attributes 表中需要一个 value 类型标识列(attribute_value_type)来知道要查看哪个列/表。
可能的方法
这是我能想到的两种可能的方法。
方法 1:具有多列的单个 EAV 表
为 patient_metadata 表创建三个不同的列 - 每个 value 类型一个。
CREATE TABLE patient_metadata (
patient_id CONSTRAINT fk_pm_patients REFERENCES patients(patient_id) NOT NULL,
attribute_id CONSTRAINT fk_pm_attributes REFERENCES metadata_attributes(attribute_id) NOT NULL,
attribute_varchar_value VARCHAR(50),
attribute_number_value NUMBER,
attribute_id_value CONSTRAINT fk_pm_values REFERENCES some_table_of_values(value_id)
);
方法 2:多个 EAV 表
创建三个不同的 patient_metadata 表 - 每个 value 类型一个。
CREATE TABLE patient_metadata_varchar (
patient_id CONSTRAINT fk_pm_patients REFERENCES patients(patient_id) NOT NULL,
attribute_id CONSTRAINT fk_pm_attributes REFERENCES metadata_attributes(attribute_id) NOT NULL,
attribute_value VARCHAR(50) NOT NULL
);
CREATE TABLE patient_metadata_number (
patient_id CONSTRAINT fk_pm_patients REFERENCES patients(patient_id) NOT NULL,
attribute_id CONSTRAINT fk_pm_attributes REFERENCES metadata_attributes(attribute_id) NOT NULL,
attribute_value NUMBER NOT NULL
);
CREATE TABLE patient_metadata_id (
patient_id CONSTRAINT fk_pm_patients REFERENCES patients(patient_id) NOT NULL,
attribute_id CONSTRAINT fk_pm_attributes REFERENCES metadata_attributes(attribute_id) NOT NULL,
attribute_value CONSTRAINT fk_pm_values REFERENCES some_table_of_values(value_id) NOT NULL
);
其他方法?
还有其他方法吗?
简而言之,我想尽可能地尊重关系完整性,让数据库知道value类型,这样它就可以执行基本的验证。但是,我相信上述两种方法都需要某种类型的手动完整性检查(方法 1 需要检查是否只填充了一个 attribute_value 列,等等)。
我将执行的查询类型将是典型的(例如检索给定元数据属性的值列表,检索值列表 用于给定患者(entity)和元数据attribute 等)。我相信在大多数情况下我需要查询 value 类型才能知道要查询哪个列或表。有没有其他办法解决这个问题?
所有方法(性能、查询结构等)的优缺点是什么?
第一次发帖,提前致谢,请随时对格式发表评论或进一步澄清!
【问题讨论】:
-
您好,我认为您遇到了一种叫做多态键现象的问题。
-
我认为这个维基百科页面涵盖了很多领域:en.wikipedia.org/wiki/…
标签: database oracle plsql database-schema entity-attribute-value