Я хочу создать таблицу метаданных пациента/образца, используя подход с атрибутом-атрибутом (EAV).
Вопрос. Как мне обрабатывать переменный тип столбца значения (например, строковый, числовой или внешний ключ в таблице словаря) на основе атрибута?
Примечание: Я не спрашиваю, следует ли использовать подход EAV. Я посмотрел на другие вопросы SO и ссылки и считаем, что это лучший подход для моего использования (например, я не хочу создавать отдельный столбец или стол для каждого атрибута, который может насчитывать сотни). Тем не менее, я, конечно же, пересмотрю другие проекты, учитывая исчерпывающий пример.
Репрезентативные данные
Пациент/образец (сущность) может иметь несколько атрибутов метаданных (например, местоположение лаборатории, выживаемость, тип опухоли), каждый из которых имеет другой тип значения (например, VARCHAR, NUMBER, FOREIGN_KEY *, соответственно).
* FOREIGN_KEY означает, что этот тип значения представляет собой идентификатор внешнего ключа (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 ???
);
Мне кажется, нужен столбец определения типа значения (attribute_value_type) в таблице metadata_attributes, чтобы узнать, какой столбец/таблицу следует искать.
Возможные подходы
Вот два возможных подхода, о которых я могу думать.
Подход 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 и т.д.).
Типы запросов, которые я буду выполнять, будут типичными (например, получить список значений для данного атрибута метаданных, получить список значений для данного пациента (объекта) и атрибута метаданных и т.д.). Я считаю, что в большинстве случаев мне нужно будет запросить тип значения, чтобы узнать, какой столбец или таблица запрашивать. Любой другой путь вокруг этого?
Каковы плюсы и минусы для всех подходов (производительность, структура запросов и т.д.)?
Первый плакат, поэтому заранее заблаговременно и, пожалуйста, не стесняйтесь комментировать форматирование или дальнейшее разъяснение!