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

вопрос создан в Wed, May 8, 2019 12:00 AM

Например, в таблице Companies есть столбцы company_name, first_contact, second_contact, а в таблице контактов есть столбцы id (PK), name, phone. Может ли таблица (компании) в SQL иметь несколько столбцов в качестве внешних ключей, которые ссылаются только на один первичный ключ другой таблицы (контактов)?

    
0
  1. С этим проблем нет. Вероятно, наиболее распространенный пример - это таблица messages, где from_user_id и to_user_id ссылаются на таблицу users.
    2019-05-08 16: 19: 25Z
  2. ДА и НЕТ. Возможно, вам придется отказаться от некоторых функций, таких как каскад удаления.
    2019-05-08 16: 20: 15Z
  3. @ P.Salmon - В чем проблема с ON DELETE CASCADE? Должно работать ИМХО.
    2019-05-08 16: 21: 26Z
  4. @ Пол Шпигель Если у вас были FK для компании и first_contact с каскадом удаления для обоих, а затем вы удалили компанию в контактах, как отреагирует mysql? Я не пробовал, так что я просто размышляю вслух.
    2019-05-08 16: 24: 29Z
  5. @ P.Salmon При удалении контакта все компании, которые ссылаются на этот контакт в first_contact или second_contact, будут удалены. То, что вы, вероятно, этого не хотите - другой вопрос. Но я не понимаю, почему это не должно работать.
    2019-05-08 16: 28: 50Z
2 ответа                              2                         

Да, вот пример:

mysql> CREATE TABLE Contacts (id INT PRIMARY KEY);
Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TABLE Companies (id INT PRIMARY KEY, company_name TEXT,
    -> first_contact INT, second_contact INT,
    -> FOREIGN KEY (first_contact) REFERENCES Contacts(id),
    -> FOREIGN KEY (second_contact) REFERENCES Contacts(id)
    -> );
Query OK, 0 rows affected (0.03 sec)

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

mysql> CREATE TABLE CompanyContacts (
    -> contact_id INT NOT NULL,
    -> company_id INT NOT NULL,
    -> is_primary BOOL NOT NULL,
    -> PRIMARY KEY (contact_id, company_id),
    -> FOREIGN KEY (contact_id) REFERENCES Contacts(id),
    -> FOREIGN KEY (company_id) REFERENCES Companies(id)
    -> );
Query OK, 0 rows affected (0.04 sec)

Некоторые преимущества:

  • Вы не ограничены двумя контактами в каждой компании.
  • Вы можете искать контакт проще - вместо поиска, если контакт встречается как first_contact или second_contact, вы просто ищете его в CompanyContacts.contact_id. Проще оптимизировать этот запрос с помощью индекса.

Некоторые недостатки:

  • Нет способа наложить ограничение, чтобы сделать хотя бы один контакт обязательным. Вы можете сделать это, объявив first_contact как NOT NULL в своем проекте, но нет ограничения SQL, которое требует наличия строки в третьей таблице для каждой компании.
  • Если вас откладывают запросы JOIN, это может быть не очень привлекательно. Но я рекомендую, чтобы вы чувствовали себя комфортно в выполнении JOINs, когда у вас есть отношения многие ко многим.
2
2019-05-08 17: 17: 13Z

Конечно! По сути, у вас было бы несколько непосредственных отношений между компаниями и контактами.

При запросе данных вам придется объединяться в таблицу контактов несколько раз (один раз для столбца, который является внешним ключом)

select *
from Companies c
join Contacts contact1 on c.first_contact=contact1.id
join Contacts contact2 on c.second_contact=contact2.id
    
0
2019-05-08 16: 18: 39Z
источник размещен Вот