Как правильно индексировать таблицу, к которой две другие таблицы имеют отношение один ко многим? - PullRequest
1 голос
/ 01 марта 2010

Представьте, что у меня есть три таблицы, называемые "клиенты", "компании" и "номера телефонов". Как клиенты, так и компании могут иметь несколько телефонных номеров. Как лучше всего индексировать номера телефона? Есть и customer_id и company_id и оставить один из них пустым? Что, если существует более двух таблиц, имеющих отношение один-ко-многим с номерами phone_numbers?

Ответы [ 4 ]

1 голос
/ 01 марта 2010

Ваши бизнес-правила могут указывать только один ко многим, но на самом деле люди и компании могут быть отношениями ко многим. У одного человека может быть много телефонных номеров (домашний, сотовый и т. Д.), И телефонный номер может относиться ко многим людям (я, мой главный друг и т. Д.). Аналогично, номер компании и номер моей компании могут совпадать - просто используйте добавочный номер, чтобы связаться со мной напрямую.

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

0 голосов
/ 01 марта 2010

Наиболее близкая вещь, которую я имею к шаблону, заключается в следующем: любые две сущности, имеющие отношение «многие ко многим», требуют ассоциативной сущности (таблицы перекрестных ссылок) между ними, вот так (предположим, суррогатные ключи): 1001 *

CREATE TABLE CUSTOMER_XREF_PHONE
( CUSTOMER_ID      NUMBER NOT NULL,
  PHONE_NUMBER_ID  NUMBER NOT NULL,
  CONSTRAINT       CUSTOMER_XREF_PHONE_PK 
    PRIMARY KEY      (CUSTOMER_ID, PHONE_NUMBER_ID),
  CONSTRAINT       CUSTOMER_XREF_PHONE_UK 
    UNIQUE           (PHONE_NUMBER_ID, CUSTOMER_ID),
  CONSTRAINT       CUSTOMER_XREF_PHONE_FK01
    FOREIGN KEY      (CUSTOMER_ID)
      REFERENCES       CUSTOMER (CUSTOMER_ID) ON DELETE CASCADE,
  CONSTRAINT       CUSTOMER_XREF_PHONE_FK02
    FOREIGN_KEY      (PHONE_NUMBER_ID)
      REFERENCES       PHONE_NUMBERS (PHONE_NUMBER_ID) ON DELETE CASCADE
);

Такой шаблон реализации может:

  • Быть полностью защищенным ограничениями ссылочной целостности на уровне базы данных

  • Поддержка двунаправленного доступа (иногда вам нужно узнать, у кого еще есть этот номер телефона)

  • Быть самоочищающимся, если ваша база данных поддерживает ON DELETE CASCADE

  • Расширяться за счет использования атрибута «тип отношения» для отображения нескольких независимых отношений между объектами, такие как:

    • У клиента есть домашний телефон
    • клиент имеет дневной номер телефона
    • клиент имеет номер факса
    • Клиент имеет номер мобильного телефона
0 голосов
/ 01 марта 2010

Я бы добавил два столбца в таблицу phone_numbers. Первым будет индекс, который скажет вам, с какой таблицей связываться (скажем, 1 = клиенты и 2 = компании). Вторым будет внешний ключ к соответствующей таблице.

Таким образом, вы можете добавить столько источников телефонных номеров, сколько захотите.

Если конкретное лицо или компания имеют более одного телефонного номера, в таблице phone_numbers должно быть несколько строк.

0 голосов
/ 01 марта 2010

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

...