Является ли один столбец частью нескольких составных ограничений FK допустимым и хорошим решением для проектирования? - PullRequest
0 голосов
/ 02 февраля 2019

Можно ли иметь один столбец в таблице как часть двух составных ограничений FK?

Скажем, у нас есть несколько филиалов нашего бизнеса, и у нас есть два разных объекта, каждый из которых принадлежит к определенной ветви.

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

Таким образом, у нас будет три таблицы:

  • EntityA
  • EntityB
  • Entities

На мой взгляд, у меня есть несколько вариантов:

1) Использованиесуррогатный ключ для всех PK

  • EntityA (entitya_id (pk), branch_id (fk), другие столбцы)
  • EntityB (entityb_id (pk), branch_id (fk), другие столбцы)
  • Сущности (entities_id (pk), entitya_id (fk), entityb_id (fk))

Проблема с этимВо-первых, мне нужно SELECT операторов внутри триггера для проверки.Я бы предпочел не делать этого.Кроме того, операторы SELECT становятся более сложными, поскольку для доступа к некоторой информации часто требуется JOIN с.

2) Используйте естественные составные ключи

  • EntityA (PK: * 1044).*, branch_id)
  • EntityB (PK: entityb_id, branch_id)
  • Entities (PK entitya_id, entitya_branch_id, entityb_id, entityb_branch_id)

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

3) Также использовать естественные составные ключи, но иметь только один столбецссылка на две таблицы

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

  • EntityA (PK:entitya_id, branch_id)
  • EntityB (PK: entityb_id, branch_id)
  • Entities (PK: entitya_id, entityb_id, branch_id)

Когда FK определен следующим образом:

CONSTRAINT `entities_entitya`
    FOREIGN KEY (`entitya_id`, `branch_id`)
    REFERENCES `entitya` (`entitya_id`, `branch_id`)
    ON DELETE CASCADE
    ON UPDATE RESTRICT,
CONSTRAINT `entities_entityb`
    FOREIGN KEY (`entityb_id`, `branch_id`)
    REFERENCES `entityb` (`entityb_id`, `branch_id`)
    ON DELETE CASCADE
    ON UPDATE RESTRICT

Итак, branch_id становится своего рода общим FK

Итак, повторю мой вопрос:

  • это законная вещь?
  • Это нарушает некоторые нормы?
  • Это как-то взорвется мне в лицо?

1 Ответ

0 голосов
/ 02 февраля 2019

В вашем решении № 3 нет ничего плохого, и я думаю, что это умное решение для вашего требования к валидации.Он точно моделирует реальное требование - оба объекта должны принадлежать к одной и той же ветви.

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

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

CREATE TABLE Entities (
  entitya_id        INT,
  entitya_branch_id INT,
  entityb_id        INT,
  entityb_branch_id INT,
  FOREIGN KEY (entitya_id, entitya_branch_id) 
    REFERENCES entitya(entitya_id, branch_id),
  FOREIGN KEY (entityb_id, entityb_branch_id) 
    REFERENCES entitya(entityb_id, branch_id),
  FOREIGN KEY (entitya_branch_id, entityb_branch_id) 
    REFERENCES EntityAffiliations(entitya_branch_id, entityb_branch_id)
)
...