Дизайн базы данных: использовать составной ключ как FK, пометить данные для обмена? - PullRequest
1 голос
/ 02 апреля 2011

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

Таблицы:

TABLE: vendor
================================
| vendor_id | name             |
--------------------------------
| 1         | ABC Limited      |
--------------------------------
| 2         | Acme Corporation |
--------------------------------

TABLE: product
=========================
| product_id | name     |
-------------------------
| 1          | Widget 1 |
-------------------------
| 2          | Widget 2 |
-------------------------

TABLE: product_color_mapping
=========================
| color_id | product_id |
-------------------------
| 1        | 1          |
-------------------------
| 2        | 1          |
-------------------------
| 3        | 1          |
-------------------------
| 1        | 2          |
-------------------------
| 4        | 2          |
-------------------------
| 5        | 2          |
-------------------------

TABLE: color
=======================
| color_id | name     |
-----------------------
| 1        | Red      |
-----------------------
| 2        | White    |
-----------------------
| 3        | Blue     |
-----------------------
| 4        | Yellow   |
-----------------------
| 5        | Green    |
-----------------------

Чтобы color.name оставался уникальным, для сопоставления товара и цвета используется таблица product_color_mapping.

В приведенном выше примере Widget 1 может быть либо Red, White, либо Blue, а Widget 2 может быть либо Red, Yellow, либо Green.

Выпуск 1:

Мне нужна таблица vendor_product для отображения фактических продуктов, которые продает продавец. Как мне хранить в базе данных, что ABC Limited продает Red Widget 1? Будет ли таблица выглядеть так:

TABLE: vendor_product
=====================================
| vendor_id | product_id | color_id |
-------------------------------------
| 1         | 1          | 1        |
-------------------------------------

Проблема, с которой я столкнулся, состоит в том, что product_id и color_id являются составным ключом в таблице product_color_mapping. Я не уверен, как правильно использовать составной ключ в качестве внешнего ключа.

Выпуск 2:

Как указано, информация о продукте и цвете будет предоставляться поставщиками. Скажем, продавец 1 не имеет продуктов и вводит свой самый первый продукт: Widget 1. Затем поставщик 1 присваивает продукту цвет Red.

  • В следующий раз, когда продавец 1 входит в другой продукт, я хотел бы предоставить Widget 1 в качестве выбираемого товара продавцу 1 (в основном, говоря: «Привет, продавец 1, вы входили в этот продукт раньше. пытаетесь войти снова? "). Поставщик 1 может либо выбрать ранее введенный продукт, либо ввести новый продукт. Если продавец 1 выбирает Widget 1, я хочу сказать: «Привет, продавец 1, вы определили предыдущий Widget 1 как цвет Red. Этот новый Widget 1 также Red?» - из которого поставщик 1 может выбрать Red или ввести новый цвет.

  • Когда появляется продавец 2, как мне разрешить ему также добавить Widget 1 в свой инвентарь БЕЗ наличия в базе данных дубликата Widget 1?

  • Наконец, как мне определить Widget 1 и Red как «действительную» информацию - и сделать ее доступной для всех поставщиков (не только для поставщика 1, который ввел информацию в первую очередь)?

ПРИМЕЧАНИЕ: Я не пытаюсь найти решение для продукта и цвета. Продукты будут иметь несколько атрибутов, связанных с ним (например, размеры, такие как «Маленький», «Средний» или «Большой»). Цвет также может иметь несколько атрибутов, связанных с ним - и эти атрибуты могут иметь свои собственные атрибуты и так далее. Продавцы будут вводить всю эту информацию.

Ответы [ 3 ]

0 голосов
/ 02 апреля 2011

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

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

             CUSTOMERA : create view CUSTOMERAPRODUCTS as select * from products where products.user='CUSTOMERA'
             CUSTOMERB:  create view CUSTOMERBPRODUCTS as select * from products where products.user='CUSTOMERB'

Вы создаете составные ключи (первичные, внешние и альтернативные уникальные) как этот [псевдосинтаксис]:

             Table: COLORS
             vendorid INT
             colorid INT
             color  varchar(20)
             PK = (vendorid, colorid)
             UNIQUE index on (vendorid, color)

             Table: PRODUCTS
             vendorid INT
             productid INT
             product varchar(20)
             PK = (vendorid, productid)
             UNIQUE index on (vendorid, product)


             Table: PRODUCTCOLORS
             vendorid INT
             productid INT
             colorid INT
             PK = (vendorid, productid)
             UNIQUE index on (vendorid, color)

             FK (vendorid, productid) references PRODUCTS(vendorid, productid)
             FK (vendorid, colorid) references COLORS(vendorid, colorid)

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

            Color values must be unique not only within the individual vendor's subset
            but unique system-wide (e.g. so that there is only one row containing 'Emerald Green')

Вы должны сделать это в таблице COLORS:

            UNIQUE index on (color)

Однако это помешаетпоставщик B не добавил «Изумрудно-зеленый» в таблицу COLORS для использования со своими продуктами, если этот конкретный цвет уже существовал в таблице, однако поставщик B не смог увидеть этот цвет, поскольку эта строка будет отфильтрована из их представлений, если «виртуальный закрытый»база данных »или какой-то аналог этого подхода действовал,

Итак, если ваша цель состоит в том, чтобы несколько притоков данных текли в общую реку данных, в которой каждый поставщик может свободно плавать, так сказать, тогдаВы можете столкнуться с беспорядочной ситуацией, которая обычно требует, чтобы таблицы, такие как COLOR и PRODUCTCATEGORY, поддерживались центральным администратором - централизованнопричиной такой ситуации обычно являются данные, которые выглядят следующим образом:

                     Emerald Green
                     Emerald-Green
                     Emmerald Green

, т.е. почти столько же «вариантов», сколько имеется притоков, поэтому ваши уникальные индексы становятся довольно неэффективными.Разве не приятно думать, что они стоят на страже.Вы можете иметь эту проблему вариантов только с одним притоком!Сложно сохранить эти таблицы в здравом уме, добавляя данные только один человек!Чтобы устранить такие помехи, требуется постоянная бдительность со стороны специального администратора данных и гораздо больше дезинфекции пакетного импорта, чем большинство компаний когда-либо готовы участвовать.

0 голосов
/ 02 апреля 2011

Еще один способ решения этой проблемы - использование нереляционных или квази-реляционных OODBMS.Вы выбрасываете нормальную форму из окна с декларативной ссылочной целостностью и думаете о данных в терминах наследования классов.У вас будет таблица основных цветов, и у каждого поставщика будет своя собственная таблица COLORS, которая «расширяет» таблицу основных цветов.Ваша OOBMBS может применять правило:

                   colorname cannot be added to Vendor A's COLORS table if it already exists in MasterColors
                   or if it already exists in Vendor A's colors table

Затем, когда вы начнете описывать продукт цветом, ваша OODMBS будет применять это правило:

                   Product.ColorId IN (select colorid from master colors UNION select colorid from VendorAColors)

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

Конечно, вы можете реализовать это в любой реляционной базе данных, но в основном это будет хранилище данных;было бы очень мало возможностей использовать декларативный RI .... (РЕДАКТИРОВАТЬ: если, конечно, ваша СУБД не позволяет вам объявлять такие ограничения для reified views.)

0 голосов
/ 02 апреля 2011

Это много вопросов.

Мне нужна таблица vendor_product для отображения фактических продуктов, которые продает продавец.Как сохранить в базе данных, что ABC Limited продает Red Widget 1?Будет ли таблица выглядеть так:

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

vendor_name    product_name    color_name
--
ABC Limited    Widget 1        Red

Я не уверен, как правильно использовать составной ключ в качестве внешнего ключа.

FOREIGN KEY (product_id, color_id) 
      REFERENCES product_color_mapping (product_id, color_id)

или

FOREIGN KEY (product_name, color_name) 
      REFERENCES product_color_mapping (product_name, color_name)

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

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

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

На стороне базы данных базовый запрос для любого из них, вероятно, будет выглядеть примерно так: SELECT ... FROM vendor_product. (Вместо этого можно использовать product_color_mapping или product.)

Когда появляется продавец 2, как мне разрешить ему также добавлять виджет 1 к своему изобретению?ory БЕЗ наличия дубликата Widget 1 в базе данных?

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

Canon Powershot A800 10 MP Digital Camera with 3.3x Optical Zoom 
Canon Powershot A800 10 M P Digital Camera with 3.3x Optical Zoom 
Canon Powershot A800 10 MP Digital Camera with 3.3x Otpical Zoom 
Canon Power Shot A800 10 MP Digital Camera with 3.3x Optical Zoom 
Canon Powershot A-800 10 MP Digital Camera with 3.3x Optical Zoom 
Canon Powershot A800 10 MP Digital Camera, 3.3x Optical Zoom 
Canon Powershot A-800 10 MP Camera, 3.3x Opt. Zoom 

Все они уникальны.(Что касается базы данных.) Задача дизайнера пользовательского интерфейса состоит в том, чтобы сделать ввод продукта настолько простым, чтобы правильно делать, что производители не склонны создавать псевдодубликаты.

НаконецКак я могу определить Widget 1 и Red как «правильную» информацию

Обычно я бы сказал, использовать внешний ключ к таблице product_color_mapping.Но кажется, что вы стремитесь иметь много разных таблиц, которые могут быть целями.«Виджет 1» и «Красный» мы уже знаем, но в дополнение к этому у вас также будут «Виджет 1» и «Маленький», а также «Виджет 1» и «Красный», а также «Виджет 1»и "Делюкс".

...