我想使用实体属性值 (EAV) 方法创建患者/样本元数据表。
问题:我应该如何根据属性处理值的不同列类型(例如字符串、数字或字典表的外键) ?
注意:我不是在问是否使用 EAV 方法。我查看了其他 SO 问题和参考资料,并相信这是我的用例的最佳方法(例如,我不想为每个属性创建单独的列或表- 可能有数百个)。但是,如果给出一个综合示例,我肯定会重新考虑其他设计。
代表性数据
一个患者/样本(实体)可以具有多个元数据属性(例如实验室位置、存活率、肿瘤类型),每个属性都具有不同的值类型(例如VARCHAR
,分别为NUMBER
、FOREIGN_KEY
*)。
*FOREIGN_KEY
表示此值类型是值INTEGER
字典表(例如 10 种可能的肿瘤类型的列表)的外键 ID ( )。所以实验室的位置可以是因为我不关心规范化这些值。但肿瘤类型应该有一定程度的验证。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 表中使用值类型标识列(attribute_value_type)来知道要查看哪个列/表。
可能的方法
这是我能想到的两种可能的方法。
方法 1:具有多列的单个 EAV 表
为 patient_metadata 表创建三个不同的列 - 每个值类型一个。
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 表 - 每个值类型一个。
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
);
其他方法?
还有其他方法吗?
简而言之,我想尽可能尊重关系完整性,让数据库知道值类型,以便它可以执行基本的验证。但是,我相信上述两种方法都需要某种类型的手动完整性检查(方法 1 需要检查是否只填充了一个 attribute_value 列,等等)。
我将执行的查询类型将是典型的(例如,检索给定元数据属性的值列表、检索给定患者(实体)和元数据属性的值列表等)。我相信在大多数情况下我需要查询值类型才能知道要查询的列或表。有没有其他办法解决这个问题?
所有方法(性能、查询结构等)的优缺点是什么?
第一次发帖,所以提前感谢,请随时对格式发表评论或进一步澄清!