2009-09-07 4 views
8

Представьте следующую базу данных:Дизайн базы данных: круговая зависимость

В таблицах «компании» есть поля id, name и flagship_product_id. В таблицах 'products' есть поля id, name и company_id.

Компания должна иметь флагманский продукт (отношения 1: 1), и все продукты имеют одну компанию (отношения 1: N).

При использовании механизма хранения, такого как MyISM, не должно быть никаких проблем с описанным выше сценарием, но при использовании движка, такого как InnoDB, возникают проблемы при вводе новых данных.

Что такое хорошее решение, за исключением разрешения отношения NULL для исходного INSERT?

Подводя итоги, компания обязательна имеет флагманский продукт.

+0

У меня очень похожая проблема, хотя InnoDB не является фактором. Круговая зависимость в схеме - проблема. –

ответ

1

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

+0

В MySQL это 'SET FOREIGN_KEY_CHECKS = 0', но это единственный способ? – LiraNuna

+0

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

+0

На прикладном уровне необходимо выполнить некоторые действия. :-) –

2

почему бы не поставить поле флагманского продукта в таблицу продуктов как логическое ... вы могли бы индекс, и CompanyID и имеют довольно быстрый поиск

+2

Индекс не влияет на бизнес-правила - кто голосовал за это ?! –

5

Вы либо будете иметь, чтобы NULLs в flagship_product или пересмотреть, как вы моделируете эту ситуацию. Подумайте о том, чтобы вместо этого поставить флагманский продукт как логическое поле на продукте. Тогда у вас нет круговой зависимости. Или укажите поле product_type для продукта, которое может иметь такие значения, как FLAGSHIP или NORMAL или OBSOLETE или что-то еще. Конечно, вы должны обеспечить это, но в прошлом я нашел это более чистым решением этой проблемы.

+0

Вы можете легко сделать этот шаг дальше и иметь таблицу PRODUCT_ATTRIBUTES, в которой перечислены атрибуты, связанные с продуктом - одним из которых может быть «FLAGSHIP». Это позволяет при необходимости использовать несколько атрибутов. – Andrew

+1

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

+0

Как я уже сказал, это должно быть соблюдено. – cletus

3

Я рекомендую использовать следующую модель данных:

Фирмы

  • company_id рк

ПРОДУКТЫ

  • PRODUCT_ID (рк)
  • company_id (Ф.К.)

FLAGSHIP_PRODUCTS

  • company_id (рк, Д)
  • PRODUCT_ID (Fk)

Создание столбца флагманом PRODUCTS таблицы не гарантирует, что только один продукт является флагманом продукт для данной компании, поскольку:

  • Уникальный ключ на колонке флагманской требует значений будет отличаться друг от друг
  • проверочного ограничения является только список допустимых значений
+0

Это усложнит запросы и повредит производительность? – LiraNuna

+3

Хорошо, что плохие данные быстро возвращаются? –

+0

Для этой модели требуется 'UNIQUE (company_id, product_id)' on 'flagship_products', правильно? Таким образом, это, в основном, сводная таблица 1: 1 (странно ...). – strager

1

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

В этой лиге не существует ни одной системы SQL.

EDIT

системы SQL отсрочили проверки ограничений, но с помощью этого можно запутаться.

0

Вот схема возможного обхода. Я не уверен, насколько высоко в масштабе Kludge это подходит, но он там.

  • Создание базы данных
  • Создать клиентов и продукты таблицы
  • вставить заполнитель или «фиктивной» строки в каждой, выполненный с возможностью ссылаться друг на друга
  • Установите FK ограничения между таблиц

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

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

+0

Это лучше, чем разрешение nulls - null, являющийся вашим невидимым зарезервированным заполнителем? –

+0

Ссылка на пустую строку или строку-заполнитель представляет собой (?) Стандартную альтернативу наличию ссылки NULL для внешнего ключа. Это как «Null» = мы не знаем, что это такое, и «Placholder» = мы знаем, что у нас нет данных, и мы активно управляем ситуацией с намеренно введенными данными. Недостатком является то, что вы должны сознательно манипулировать/кодировать местозаполнитель ... но тогда вам придется делать то же самое с нулями, так почему бы не сделать его более очевидным, что происходит? –

0

Вам необходимо разбить цикл на deferring один из ваших ограничений ссылочной целостности до конца транзакции.

Пожалуйста, зайдите в Google для «НАЧАЛЬНО ОТРАЖЕННОГО ОТВЕРСТИЯ».

(не уверен, поддерживает ли InnoDB это)

Смежные вопросы