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

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

У меня есть дизайн для системы заказов, игнорируя все, что не относится к этому примеру, который у меня остался:

  • Кредитная карта
  • Покупатель
  • Заказ

Я хочу так, чтобы,

  • Клиенты могут иметь кредитные карты (0-n)
  • У клиентов есть заказы (1-n)
  • Заказы имеют один клиент (1-1)
  • Заказы имеют одну кредитную карту (1-1)
  • Кредитные карты могут иметь одного клиента (1-1) (уникальные идентификаторы, поэтому мы можем игнорировать уникальность номера копии, муж/жена могут делиться экземплярами копии и т. д.)

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

По сути, это создает круговой дизайн между тремя столами.

Возможные решения: Либо

Создайте круговой дизайн, дайте ссылки:

  • ссылка на заказ,
  • ссылка клиента на копию
  • ссылка клиента на заказ

or

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

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

Мои вопросы,

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

Спасибо и дайте мне знать, если есть что-то, что вам нужно уточнить / объяснить.

--Обновить/Изменить--

Я заметил ошибку в заявленных требованиях. В основном упал мяч, пытаясь упростить вещи для SO. Там есть еще одна таблица для платежей, которая добавляет еще один слой. Загвоздка в том, что заказы могут иметь несколько платежей, с возможностью использования разных кредитных карт. (если вы действительно хотите знать даже другие формы оплаты).

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


person Louis    schedule 27.04.2009    source источник


Ответы (5)


Клиент может иметь 0 или более связанных кредитных карт, но связь является динамической — она может появляться и исчезать. И, как вы указываете, кредитная карта может быть связана с более чем одним клиентом. Таким образом, получается таблица n:m, возможно, со столбцом флага для «активного».

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

person dkretz    schedule 27.04.2009
comment
Спасибо, чтобы уточнить, вы имеете в виду хранить детали копии с заказом в TOS в новой таблице, эффективно сохраняя ее избыточно (не то чтобы это плохо в этом случае)? Или вы имели в виду просто сохранить ссылку на таблицу CC? - person Louis; 27.04.2009
comment
Чтобы уточнить это, он должен быть в новой таблице, независимо от того, таблица заказов не может быть изменена, чтобы содержать детали CC, поскольку мы также имеем дело с другими типами платежей. - person Louis; 27.04.2009
comment
Верно. Какими бы ни были факты на момент продажи, вам нужен моментальный снимок, потому что это контрольный след финансовой транзакции. Целесообразно было бы создать отдельную таблицу «Платежи» или разные таблицы для платежей наличными и безналичных расчетов. Также имейте в виду, что существует риск хранения слишком большого количества копий информации, связанной с клиентами, из-за проблем с конфиденциальностью. - person dkretz; 27.04.2009
comment
Я думаю, что может быть достаточно оставить его в таблице кредитных карт и просто использовать ссылку, таблицы могут быть заблокированы с функциями только для чтения, так что этот снимок не нужен. И вы правы, есть проблемы с его сохранением, мы находимся в процессе обеспечения совместимости с PCI, и эти изменения произойдут после этого начального этапа. - person Louis; 27.04.2009

Думаю проблема в моделировании Ордена. Вместо того, чтобы у одного Заказа была одна кредитная карта, заказ должен быть связан с более чем одной кредитной картой, из которых только одна активна в любой момент времени. По сути, «Заказ и кредит» — это «многие ко многим». Чтобы смоделировать это в БД, вам нужно ввести ассоциативную таблицу, скажем, PaymentHistory. Теперь, когда для заказа требуется новая кредитная карта, вы можете просто создать новую кредитную карту, связать ее с заказом и пометить связанную историю платежей как активную.

person Journeyman Programmer    schedule 27.04.2009
comment
Да, это была одна из моих первых попыток, но я решил, что будет понятнее, чтобы кредитные карты принадлежали клиентам, поскольку на самом деле они принадлежат клиентам, а не заказам. (У нас есть постоянные клиенты, которые хотят использовать один и тот же CC, запрос их старых заказов будет хаком, особенно если старые заказы когда-либо будут заархивированы.) - person Louis; 27.04.2009
comment
Почему Кредитная карта не может быть связана как с Заказом, так и с Покупателем? «Клиент и кредитная карта» — «один ко многим», «Клиент и заказ» — «один ко многим», а «Заказ и кредитная карта» — «многие ко многим». - person Journeyman Programmer; 27.04.2009
comment
Заказ и кредитная карта 1 к 1, но связь динамическая - person Louis; 27.04.2009

Хм?

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

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

  • Клиент: id, текущая карта
  • Кредитные карты: идентификатор, номер, customer_id
  • Заказ: id, Card_id, Customer_id

Изменить: Ой, забыл поле, спасибо.

person Tordek    schedule 27.04.2009
comment
Заказ: id, Card_id, Customer_id - person Louis; 27.04.2009
comment
Итак, почему заказ-›клиент-›cc-›заказ не цикличен? - person Louis; 27.04.2009
comment
Потому что это не то, что меняется. Заказ-›Клиент что-то значит. Клиент-›CC означает нечто иное. Когда клиент заказа меняется, его не волнует кредитная карта нового клиента по умолчанию, а только та, о которой он уже знает. - person Tordek; 27.04.2009
comment
Не то, чтобы клиент когда-либо менялся, но то, что вы говорите, является одной из ловушек, связанных с циклическими зависимостями. В вашем примере: до того, как клиент изменился, вы можете сделать вывод о клиенте по кредитной карте и идентификатору клиента в заказе, после этого изменения целостность и отношения будут нарушены. - person Louis; 27.04.2009
comment
Кроме того, представьте, что клиент звонит и хочет знать, какие у него заказы на основе номера кредитной карты (я знаю пример дерьма, этого никогда не произойдет), вы не можете сказать, что это все их заказы без вторичного запрос. - person Louis; 27.04.2009
comment
Он не является циклическим, потому что таблица кредитных карт не ведет учет заказов, для которых она используется; в таблице заказов хранится информация о кредитных картах, которые использовались для заказа. - person Jonathan Leffler; 27.04.2009
comment
То, что вы говорите, не скользит по мне, клиент и копия имеют отношения, которые могут сделать вывод о том, что заказ только наоборот. Либо я чего-то не понимаю, либо вы не понимаете сути. Пожалуйста, объясните подробнее, если можете, я знаю, как воспринимать критику, даже если она явно неправа :P - person Louis; 28.04.2009

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

Это удобно, когда вы меньше всего этого ожидаете.

person Joshua    schedule 27.04.2009

Это год, но есть некоторые моменты, которые стоит отметить.

NB Для онлайн-процессов БЕЗ СЧЕТА: Клиента лучше определить как Покупателя, и также, вероятно, будет другой тип клиента - Бенефициар/Получатель. Вы можете покупать авиабилеты, цветы и т. д. для других людей, поэтому эти две роли должны быть четко разделены, поскольку они включают разные бизнес-процессы (одна для оплаты, а другая для отправки товара).

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

ПОТРЕБИТЕЛИ С УЧЕТНОЙ ЗАПИСЬЮ: Единственным исключением будет случай, когда кто-то открыл учетную запись и предоставил информацию о своей кредитной карте для использования в последующих покупках. В таком случае изменения информации о кредитной карте будут происходить вне транзакции — как часть процесса управления счетом.

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

person Community    schedule 29.05.2010