Лучший способ расширить информацию о реляционной базе данных

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

  • Телефон: процессор, оперативная память, хранилище...
  • Телевизор: размер, разрешение...

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

Чтобы соответствовать этому, теперь у меня есть одна общая таблица с именем Products (с идентификатором автоматического увеличения) и одна подчиненная таблица для каждого типа продукта (ProductsPhones, ProductsTV...) со спецификациями и связанная с принципалом с помощью внешнего ключа.

Я считаю это решение неэффективным, так как таблица Products имеет только один столбец (автоматически увеличивающийся идентификатор).

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


person Community    schedule 15.02.2017    source источник


Ответы (3)


Краткий ответ: нет. Реляционная модель — это логическая модель первого порядка, означающая, что предикаты могут варьироваться в отношении сущностей, но не в отношении других предикатов. Это означает, что зависимые типы и модели EAV не поддерживаются.

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

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

Позже вы можете найти применение таблице Products для хранения общих атрибутов, таких как Type, Serial number, Cost, Warranty duration, Number in stock, Warehouse, Supplier и т. д.

person reaanb    schedule 15.02.2017
comment
если возможно, не могли бы вы уделить минуту, чтобы объяснить, почему мой ответ не является реляционным? - person Forklift; 15.02.2017

Наличие таблицы «Продукты» — это хорошо. Вы можете поместить туда все столбцы, общие для всех типов, такие как название продукта, описание, стоимость, цена, и это только некоторые из них. Так что это не просто автоматически увеличивающийся идентификатор. Рекомендуется использовать внутренний идентификатор типа int или long int в качестве первичного ключа. Вы также можете добавить еще одно поле «код» или как вы хотите его назвать для ввода пользователем или удобного для пользователя, что характерно для систем управления продуктами. Убедитесь, что вы проиндексировали его, если он используется в критериях поиска или запроса.

ХТН

person cham    schedule 15.02.2017

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

У вас могут быть такие таблицы:

-- what are the products?
Products (Id, ProductTypeId, Name)

-- what kind of product is it?
ProductTypes (Id, Name)

-- what attributes can a product have?
Attributes (Id, Name, ValueType)

-- what are the attributes that come with a specific product type?
ProductTypeAttributes (Id, ProductTypeId, AttributeId)

-- what are the values of the attributes for each product?
ProductAttributes (ProductId, ProductTypeAttributeId, Value)

Итак, для телефона и телевизора:

ProductTypes (1, Phone) -- a phone type of product
ProductTypes (2, TV)     -- a tv type of product

Attributes (1, ScreenSize, integer) -- how big is the screen
Attributes (2, Has4G, boolean) -- does it get 4g?
Attributes (3, HasCoaxInput, boolean) -- does it have an input for coaxial cable?

ProductTypeAttributes (1, 1, 1) -- a phone has a screen size
ProductTypeAttributes (2, 1, 2) -- a phone can have 4g
-- a phone does not have coaxial input
ProductTypeAttributes (3, 2, 1) -- a tv has a screen size
ProductTypeAttributes (4, 2, 3) -- a tv can have coaxial input
-- a tv does not have 4g (simple example)

Products (1, 1, CoolPhone) -- product 1 is a phone called coolphone
Products (2, 1, AwesomePhone) -- prod 2 is a phone called awesomephone
Products (3, 2, CoolTV) -- prod 3 is a tv called cooltv
Products (4, 2, AwesomeTV) -- prod 4 is a tv called awesometv

ProductAttributes (1, 1, 6) -- coolphone has a 6 inch screen
ProductAttributes (1, 2, True) -- coolphone has 4g
ProductAttributes (2, 1, 4) -- awesomephone has a 4 inch screen
ProductAttributes (2, 2, False) -- awesomephone has NO 4g
ProductAttributes (3, 3, 70) -- cooltv has a 70 inch screen
ProductAttributes (3, 4, True) -- cooltv has coax input
ProductAttributes (4, 3, 19) -- awesometv has a 19 inch screen
ProductAttributes (4, 4, False) -- awesometv has NO coax input

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

person Forklift    schedule 15.02.2017
comment
Ваша модель действительна в SQL, но не является реляционной, поскольку домен столбца Value в ProductAttributes зависит для каждой строки от значения поля ProductTypeAttributeId. 1NF требует, чтобы каждый компонент отношения имел один домен. Например, ProductAttributes (1, 1, True) не будет допустимой строкой, но это нельзя предотвратить с помощью ограничения внешнего ключа. Модели EAV требуют более высокой формы логики, чем используемая в реляционной модели. - person reaanb; 15.02.2017
comment
Да все верно. В некоторых случаях способность SQL представлять данные, отличные от 1NF, на самом деле может быть преимуществом, но ее следует использовать осторожно, чтобы не создавать несоответствий. - person reaanb; 15.02.2017
comment
@Forklift, ваш подход удобен, когда требуется настройка конечного пользователя, например, требуется поддержка настраиваемых полей. Например, в мультитенантном приложении, где у каждого арендатора могут быть разные поля, необходимые или необходимые для их бизнеса. Недостатком является то, что настраиваемые поля не идеальны для поиска, если не применяется другой метод. - person cham; 16.02.2017