Реализация пользовательских полей - PullRequest
1 голос
/ 17 июля 2009

Я создаю лабораторную базу данных, которая анализирует множество образцов из разных мест. Некоторые местоположения хотят, чтобы их собственный ссылочный номер (или другие атрибуты) хранился в образце.

Как мне представить столбцы, которые относятся только к подмножеству моих выборок?

Вариант 1: Создать отдельную таблицу для каждого уникального набора атрибутов?
SAMPLE_BOILER: sample_id (FK), tank_number, boiler_temp, lot_number
SAMPLE_ACID: sample_id (FK), vial_number
Этот вариант кажется слишком утомительным, особенно по мере роста системы.

Опция 1a: Наследование таблиц классов ( ссылка ): Дерево с общими полями во внутреннем узле / таблице
Опция 1b: Наследование конкретной таблицы ( ссылка ): Дерево с общими полями в листовом узле / таблице

Вариант 2: Поместите каждый атрибут, относящийся к любому образцу, в таблицу SAMPLE.
Большинство столбцов каждой записи, скорее всего, будут иметь значение NULL, однако все поля хранятся вместе.

Опция 3: Создание _VALUE_ таблиц для каждого используемого типа данных Oracle.
Этот вариант гораздо сложнее. Получение всех атрибутов для образца требует доступа ко всем таблицам ниже. Однако система может динамически расширяться без отдельных таблиц для каждого нового типа образца.

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: (Добавить свой вариант)

Ответы [ 9 ]

3 голосов
/ 24 июля 2009

Чтобы помочь с поиском в Google, ваш третий вариант немного похож на шаблон Entity-Attribute-Value , который обсуждался в StackOverflow до , хотя часто критически.

Как и другие предлагали, если это вообще возможно (например, когда система запущена и работает, появится несколько новых атрибутов), вам следует использовать вашу реляционную базу данных обычным способом с таблицами в качестве типов и столбцами в качестве атрибутов - ваш Вариант 1. Начальная настройка будет стоить того позже, так как ваша база данных начнет работать так, как она была спроектирована.

Еще одна вещь для рассмотрения: вы привязаны к Oracle? Если нет, то существуют нереляционные базы данных, такие как CouchDB , которые не ограничены предварительными схемами так же, как реляционные базы данных.


Редактировать : вы спрашивали об обработке новых атрибутов в варианте 1 (теперь 1a и 1b в вопросе) ...

  • Если вариант 1 является подходящим решением, новых атрибутов достаточно мало, чтобы допустимы издержки на изменение схемы базы данных для их размещения, поэтому ...

  • вы будете писать сценарии базы данных для изменения таблиц и добавления столбцов, поэтому в этих сценариях можно легко обработать значение по умолчанию.

Из двух вариантов 1 (1a, 1b) моими личными предпочтениями будет наследование конкретной таблицы (1b):

  • Это самая простая вещь, которая работает;
  • Для каждого запроса требуется меньше объединений;
  • Обновления проще, так как вы записываете только в одну таблицу (отношения FK не поддерживаются).

Хотя любой из этих первых вариантов является лучшим решением, чем другие, и нет ничего плохого в методе наследования таблиц классов, если вы предпочитаете именно это.

Все сводится к тому, как часто появляются действительно новые атрибуты .

  • Если ответ «редко», то случайное обновление схемы может справиться.

  • Если ответ «много», то модель реляционной БД (с фиксированными встроенными схемами) - не лучший инструмент для работы, поэтому решения, которые ее включают (entity-attribute-value, Столбцы XML и т. Д.) Всегда будут казаться немного трудоемкими.

Удачи, и дайте нам знать, как вы решаете эту проблему - это общая проблема, с которой сталкиваются люди.

1 голос
/ 30 июля 2009

Вы действительно должны использовать Вариант 1. Хотя это более утомительно для создания, Вариант 2 и 3 откусит вас назад при попытке запросить данные. Запросы станут более сложными.

На самом деле, самая важная часть хранения данных - это запрос. Вы не упомянули, как вы планируете использовать данные, и это является важным фактором при проектировании базы данных. Насколько я вижу, первый вариант будет наиболее простым для запроса. Если вы планируете использовать инструменты отчетности или ORM, они также предпочтут это, так что вы оставляете свои варианты открытыми.

На самом деле, если вы находите создание таблиц утомительным, попробуйте использовать ORM с самого начала. Хорошие ORM помогут вам с самого начала создавать таблицы.

1 голос
/ 24 июля 2009

Опция 1 , за исключением того, что это не отдельная таблица для каждого набора атрибутов: создайте отдельную таблицу для каждого образца источник .

т.е. из ваших примеров: образцы из котла будут иметь номер бака, температуру котла, номер партии; Образцы кислот имеют номер флакона.

Вы говорите, что это утомительно; но я полагаю, что чем больше работы, которую вы потратите на сбор и кодирование значения данных, теперь принесут огромные дивиденды, тем позже вы сэкономите в долгосрочной перспективе, потому что ваши отчеты будут легче составлять, понимать и поддерживать. Эти парни из котельной спросят: «Нам нужно знать общее значение Х для бака, сгруппированного по этому набору температурных диапазонов котла», а вы скажете: «Нет проблем, дайте мне полчаса», потому что вы сделали все возможное ярдов уже.

Вариант 2 будет моим запасным вариантом, если вариант 1 окажется излишним. Вы все еще хотите проанализировать, какие поля необходимы, каковы их типы данных и ограничения.

Опция 4 заключается в использовании комбинации опций 1 и 2. Вы можете обнаружить, что некоторые атрибуты являются общими для множества типов выборок, и для этих атрибутов может иметь смысл жить в основной выборке. Таблица; тогда как другие атрибуты будут очень специфичны для определенных типов образцов.

0 голосов
/ 30 сентября 2009

CodeSpeaker, Мне нравится ваш ответ, он направляет меня в правильном направлении для решения аналогичной проблемы. Но как бы вы справились со значениями выпадающего списка? Я имею в виду таблицу значений Lookup, так что многие поиски ссылаются на один UserDefinedField. Но у меня также есть еще одна проблема, чтобы добавить к смеси. Каждое поле должно иметь несколько связанных языков, поэтому каждое значение должно ссылаться на эквивалентное значение для нескольких языков. Может быть, я слишком много думаю об этом, поскольку у меня пока есть около 6 столов.

0 голосов
/ 30 июля 2009

Я работаю как на коммерческой, так и на домашней системе, где пользователи имеют возможность динамически создавать свои собственные поля / элементы управления. Это упрощенная версия того, как это работает.

Таблица:

  • Страницы
    • Управление
      • Значения

Страница - это просто контейнер для одного или нескольких элементов управления. Ему можно дать имя.

Элементы управления связаны со страницами и представляют собой элементы управления пользовательского ввода. Элемент управления содержит, какой это тип данных (int, string и т. Д.) И как он должен быть представлен пользователю (текстовое поле, выпадающий список, флажки и т. Д.).

Значения - это фактические данные, которые пользователи ввели в элементы управления, значение содержит один столбец для каждого типа данных, который он может представлять (int, string и т. Д.), И в зависимости от типа элемента управления соответствующий столбец устанавливается с помощью пользовательский ввод.

В Values ​​есть дополнительный столбец, в котором указывается, к какой группе принадлежит значение. Каждый раз, когда пользователь заполняет форму элементов управления и нажимает кнопку «Сохранить», значения, введенные в элементы управления, сохраняются в одной группе, поэтому мы знаем, что они принадлежат друг другу (инкрементный счетчик).

0 голосов
/ 24 июля 2009

Это может быть глупый вопрос, но что вам нужно делать со значениями атрибута? Если вам нужно только отобразить данные, просто сохраните их в одном поле, возможно, в формате XML или в каком-либо сериализованном формате.

Вы всегда можете использовать таблицу шаблонов для определения образца «тип» и доступных полей, которые вы отображаете для целей ввода данных.

Если вам нужно отфильтровать их, единственная эффективная модель - это вариант 2. Как и все остальные, стиль 3-х значений сущности-атрибута является несколько ментальным и работать с ним не очень интересно. Я пробовал это сам в прошлом и однажды реализовал, я хотел бы не беспокоиться.

Постарайтесь создать свою базу данных, основанную на том, как ваши пользователи должны взаимодействовать с ней (и, следовательно, на том, как вам нужно ее запрашивать), а не просто моделировать данные.

0 голосов
/ 24 июля 2009

Если набор примерных атрибутов был относительно статичным, то прагматичным решением, которое облегчит вашу жизнь в долгосрочной перспективе, будет option # 2 - это все атрибуты SAMPLE, поэтому все они должны быть в той же таблице.

Хорошо - вы могли бы собрать хорошую иерархию объектов базовых атрибутов с различными расширениями, но это будет больше проблем, чем стоит. Будь проще. Вы всегда можете собрать несколько видов подмножеств выборочных атрибутов.

Я бы выбрал вариант вашего варианта №3 только в том случае, если список примеров атрибутов был очень динамичным и ваши пользователи должны были иметь возможность создавать свои собственные поля.

С точки зрения реализации динамических пользовательских полей, вы можете сначала прочитать комментарии Тома Кайта к этому вопросу . Теперь Том может быть довольно настойчивым в своих взглядах, но я беру из его комментариев, что вы должны быть очень уверенными, что вам действительно нужна гибкость для того, чтобы ваши пользователи могли добавлять поля на лету, прежде чем делать это. , Если вам действительно нужно это сделать, не создавайте таблицу для каждого типа данных - это заходит слишком далеко - просто храните все в 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)
);

Теперь ... это выглядит злым, не так ли? Вы действительно хотите поехать туда?

0 голосов
/ 18 июля 2009

Что бы вы ни делали, вариант 3 ужасен, каждый запрос будет объединять данные, чтобы создать ОБРАЗЕЦ. Похоже, у вас есть несколько общих полей SAMPLE, которые необходимо объединить с более конкретными данными для типа сэмпла. Рассматривали ли вы некоторые пользовательские поля.

Пример:

<code>
  SAMPLE_BASE: sample_id(PK), version, status, date_create, name, userdata1, userdata2, userdata3
  SAMPLE_BOILER: sample_id (FK), tank_number, boiler_temp, lot_number
0 голосов
/ 17 июля 2009

Я бы основал ваше решение на том, как вы обычно видите данные. Например, если вы получаете 5-6 новых атрибутов в день, вы никогда не сможете продолжать добавлять новые столбцы. В этом случае вы должны создать столбцы для «стандартных» атрибутов и добавить макет «ключ / значение», аналогичный вашему «Варианту 3».

Если вы не ожидаете увидеть это, я бы сейчас выбрал вариант 1 и изменил ваш дизайн на «Вариант 3», только если вы дойдете до того, что он превращается в слишком много работы. Может случиться так, что у вас будет 25 атрибутов, добавленных за первые несколько недель, а затем ничего за несколько месяцев. В этом случае вы будете рады, что не сделали дополнительную работу.

Что касается варианта 2, я обычно советую против этого, поскольку значение Null в реляционной базе данных означает, что значение равно «Неизвестно», а не то, что оно «не применяется» к конкретной записи. Хотя в прошлом я не соглашался с этим с людьми, которых я в целом уважаю, поэтому я бы не стал начинать какие-либо войны из-за этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...