Схема базы данных, которая может поддерживать специализированные свойства

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

Решение

Хранилище данных является реляционной СУБД, и это не обсуждается:-) В частности, это Microsoft SQL Server 2005.

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

Еще одна идея заключается в создании таблицы

reading(<common properties>, extended_properties)

и поле extended_properties является некоторой сериализацией расширенных свойств. Я думал о JSON или XML. Скорее всего, я буду использовать структуру ORM, но я еще не решил. В любом случае объектное представление специализированного объекта из reading может вывести словарь {extended_property_name, value}, содержащий пар синтаксического анализа/значения из поля extended_properties.

Из этого http://msdn.microsoft.com/en-us/library/ms345117(SQL.90).aspx Я понимаю, что поля XML, в сочетании со схемами для них, дают понятие типизированного XML внутри СУБД. Кроме того, запросы, связанные с содержимым XML в поле extended_properties, также могут учитывать это.

Что я хочу

Обратная связь с моими решениями, в первую очередь с таблицей reading и сериализацией расширенных свойств.

Кроме того, я понимаю, что это одно из ограничений реляционной СУБД по сравнению с хранилищами, основанными на значении/ценности. Тем не менее, наверняка должны быть некоторые методы моделирования, чтобы удовлетворить это.

Любая обратная связь очень ценится!

Ответ 1

Андерс, не отказывайтесь от какой-либо целостности или твердости, например, типа безопасности.

(Приближение ответа).

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

Этот вопрос часто возникает, но искатель всегда имеет узкую перспективу; Я продолжаю делать одни и те же утверждения (подмножество) из неизменяемого набора. Идея состоит в том, чтобы оценить все варианты. Поэтому я пишу документ. К сожалению, это занимает больше времени. Возможно 4 страницы. Не готов к публикации. Но диаграммы закончены, я думаю, что вы на балу, и вы можете использовать его сразу.

Предупреждение: опытные инженеры по строительству проектов
Дорога не подходит для караванов или читателей с высоким коэффициентом Eek.

Ссылка на ▶ Четыре альтернативных модели данных ◀ в документе, находящемся в процессе разработки. Извинения за беспорядок на полу; Я скоро уберу.

▶ Ссылка на IDEF1X Notation ◀ для всех, кто не знаком со стандартом для моделирования реляционных баз данных.

  • Все они реляционные, с полной целостностью.

  • Параметры 6NF. Реляционная сегодня (SQL) не обеспечивает поддержку для 6NF; он не запрещает это, он просто не предоставляет структуры 5NF➔6NF. Поэтому вам нужно создать небольшой каталог, который некоторые называют "метаданные". Действительно, это просто расширение стандартного каталога SQL (таблицы sys). Требуемый уровень контроля моделируется в каждом варианте.

  • По существу EAV выполняется правильно, с полным контролем и целостностью (тип безопасности, декларативная ссылочная целостность и т.д.), а не как обычно.

Вам могут быть интересны эти связанные вопросы/ответы (в частности, посмотрите на Модели данных):

Несколько фиксированных и абстрактных гибких

Проблема с привязкой к схеме базы данных

"Простая" проблема с дизайном базы данных

Ответ на комментарии

... Таким образом, мы можем легко захватить строки "Комментарий", связанные с данным экземпляром специализированного типа. Это способ сделать это, или я буду сожалеть об этом решении позже? Есть ли какой-либо другой шаблон, который нам не хватает?

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

Модель данных

Какова цель таблицы ProductType в примере вашего продукта 5NF/подтип? Он содержит строку, соответствующую каждому специализированному продукту, например, ProductCPU? Я предполагаю, что он указывает, какой специализацией является базовый продукт.

(Малая критическая ошибка на диаграмме, исправлена.)

Да, точно.

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

  • (Оцените, как изменяется ProductType, в точности, какую роль он играет, для каждой из четырех моделей данных.)

  • "Обобщение-специализация" - это все mumbo jumbo, OO-терминология; не пересекая линию и узнавая, что Реляционность способна на 30 лет. Если вы немного узнаете о Relational, у вас будет полная сила; в противном случае вы ограничены очень ограниченным подходом OO ко всему (у Амблера и Фаулера есть что ответить). Пожалуйста, прочитайте этот пост, от 11 декабря 10и далее. Модель реляционных баз данных Объекты, а не объекты; не классы.

Например, при добавлении нового продукта вы хотите указать, скажем, раскрывающийся список, какие типы продуктов можно добавить. Основываясь на этом выборе, можно определить, в какие таблицы помещать данные. Правильно? Мне жаль, что я говорю о коде приложения, но мне просто нужно поставить его в перспективе

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

Не стоит говорить о коде приложения, который будет использовать Rdb, они идут вместе, как муж и жена (а не муж и раб).

  • Для ваших классов OO сопоставьте дерево классов с Rdb, как только вы закончите моделирование Rdb, независимо от любого приложения, которое будет его использовать. А не наоборот. И не зависит от одного приложения.

  • Забудьте о "сохранении", у него много проблем ( "Потерянные обновления", "Повреждение целостности данных", "Проблематичная отладка", "Массовое разглашение" и т.д.). Все обновления для Rdb должны быть в транзакциях с соблюдением ACID, доступными в течение 30 лет, но Fowler и Ambler еще не читали об этом. Обычно это означает, что один хранимый proc pre xact.

Дискриминант является FK для таблицы типов, как мы установили ранее. Он обозначает, какой тип spec. применяется к базовому типу. Но что содержит таблица дискриминантов?

Не ясно ли это из модели данных? ProducType CHAR(1) или (2). Name Char(30).

Может быть удобным для отображения текстом, указывающим тип для целей пользовательского интерфейса,

Да, между прочим, например, контроль, противопоставление и т.д., устранение двусмысленности при кодировании или отчетности.

но также содержит точное имя таблицы, которое содержит специализированный тип?

Нет. Это было бы слишком физически, чтобы быть помещенным в данные. Запрещено по принципу.

Но это необязательно.

Скажите, что меня интересует Продукт с ID = 1. У него есть дискриминант, указывающий, что это ProductCPU. Как вы могли бы получить этот ProductCPU из вашего кода приложения?

Это будет легко, если вы возьмете предоставленную модель и внесете ее (все таблицы) в виде классов правильно и т.д. В запросе, который вы запрашиваете, не будет использоваться Views (для списков и более общего использования). Псевдокодом будет:

  • с учетом ProductId (Подтип неизвестен, поэтому вы не должны сидеть в определенном подтипе окне), загрузите только супертип Product
  • на основе Дискриминатора Product.ProductType, установить индикаторы и т.д. и загрузить применимый подтип, один из ProductCPU; ProductMemory; ProductDisk; ProductTape; и др.

  • Я видел (и не согласен с) методы OO, которые загружают все подтипы для данного ProductId сразу: один подтип действителен; а остальные недействительны. Код по-прежнему должен ограничивать действительный класс для Product на основе Product.ProductType.

Альтернативно, например. где контекст, пользователь сидит в определенном подтипом окне, например. ProductCPU, с установленным классом и запросами ProductId xxx. Затем используйте ProductCPU Вид. Если он возвращает нулевые строки, он не существует.

  • Может быть ProductDisk xxx, но не ProductCPU xxx. Как вы справляетесь с этим, указав ли вы, что есть Product`xxx, но он не является процессором или не зависит от требований приложения.

Для списков, где приложение заполняет сетку, независимо от ProductId, используйте представления (по одному на каждый) для загрузки каждой сетки. Этот SQL основан на соединении и не требует ссылки на ProductType.

Ответ 2

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

Причина: вы говорите, что ваша реализация будет выполнена в СУБД, и это не подлежит обсуждению. Хорошо. Сбрасывание неструктурированных, похожих на blob вещей, таких как сериализованная хеш-таблица в поле БД, противоречит философии дизайна RDBMS, так что у вас будет серьезный удар по эффективности, если вы не согласны с идеей рассматривать поле * extended_properties * как непрозрачное blob, так же, как gif или другой двоичный объект.

Другими словами, забудьте запросить (эффективно) "все объекты с расширенным свойством COLOR = RED".

Проблема, которую вы имеете (описывая таксономии ОО в РСУБД), определенно не нова. Посмотрите этот, чтобы получить подробное описание параметров.

Ответ 3

Это классический пример шаблона проектирования gen-spec. Gen-spec рассматривается в каждом учебном пособии по объектовому моделированию, потому что он обрабатывается наследованием. Он часто пропускается в учебниках по моделированию реляционных данных. Но это хорошо понято.

Сделайте веб-ссылку на "реляционное моделирование специализации обобщения". Вы увидите несколько статей о том, как настроить единую таблицу для общего класса и таблицы для каждого специализированного класса. Статьи помогут вам в разработке внешнего ключа. В частности, первичный ключ каждой специализированной таблицы выполняет двойной долг. Это также внешний ключ к обобщенной таблице.

Это не будет выглядеть вам знакомым, если вы используете объектное моделирование. Но вы обнаружите, что он работает хорошо. И решение, предлагаемое большинством статей, не является динамическим, поэтому вам придется делать DDL каждый раз, когда обнаруживается новый специализированный подкласс.

Ответ 4

Вот пять примеров из SO. Какой из них будет зависеть от фактической проблемы, которую вы решаете, и от вашего предпочтения.

В общем, я бы посоветовал не сериализовать данные в поля БД.

Если относительно немного специализированных версий сущности вы можете просто использовать подтипы, как в этих примерах: пример один, пример два.

При больших значениях свойств или если свойства должны быть определены динамически (без изменений схемы), посмотрите на реализацию шаблона наблюдения, как в этих примерах: пример три, пример четыре; или в так называемую 6-ю нормальную форму, как описано в: пример пять. Обратите внимание, что "шаблон наблюдения" представляет собой упрощенную версию 6-го NF.

Ответ 5

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

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

Unique_Property_ID
, FK_To_Some_Entity (Not sure what entity these link to: customers, bills, etc.) 
, Property_Type Not the data type but a link to a table describing this entity)
, Property_Value (Difficult to determine if all of your values will be of the same type: string, int, date, etc.)

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

VehicleID   Property Type  Property Value
3           Sound System   Bose
3           Hybrid System  Battery
7           Starter Type   Hand Crank
7           Passenger Seat Rumble
9           Starter Type   Kick Start
9           Passenger Seat Side Car

Каждое значение для каждого набора | тип свойства будет иметь свою собственную запись.

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