#sql #database
#sql #База данных
Вопрос:
Пример сценария: у 1 сотрудника будет только 1 адрес, а 1 адрес будет принадлежать только этому 1 сотруднику. Ниже приведены 2 варианта, которые являются правильными или ни тем, ни другим? Больше всего меня смущает, должен ли я поместить первичный ключ сотрудника в таблицу адресов или поместить первичный ключ адреса в таблицу сотрудников?
Я использую PostgreSQL, поскольку некоторым из вас нужно знать, какую базу данных я использую.
Вариант 1
Employee
EmployeeId (PK)
EmployeeName
AddressId (FK)
Address
AddressId (PK)
AddressLine1
Вариант 2
Employee
EmployeeId (PK)
EmployeeName
Address
AddressId (PK)
AddressLine1
EmployeeId (FK)
Комментарии:
1. Что, если два сотрудника живут по одному адресу? Что происходит, когда сотрудник перемещается?
2. Если два сотрудника живут по одному адресу, это было бы хорошо, потому что первичный ключ в таблице адресов всегда будет разным. Если сотрудник перемещается, конкретный AddressID также должен быть обновлен.
3. Какую СУБД вы используете? На самом деле невозможно иметь истинные отношения 1: 1, если ваша СУБД не поддерживает отложенные ограничения, и, к сожалению (например) MS SQL Server их не поддерживает. Альтернативный подход заключается в использовании a
VIEW
, который представляет допустимые парные данные, в то время как базовая таблица скрыта от кода приложения и запросов.4. Я думаю, вы слишком жестки — когда дело доходит до хранения почтовых адресов для других объектов в
1:1
отношениях, проще просто сделатьAddress
таблицу простым хранилищем данных, которое не содержит собственных FK, что также позволяет использоватьAddresses
таблицу для хранения адресов, неEmployee
относящихся к записям, например, клиенты.5. Объясните, почему вы считаете, что необходимы две таблицы.
Ответ №1:
Есть ли у сотрудника адрес или у адреса есть сотрудник?
Я бы сказал, у сотрудника есть адрес. Я бы подумал, что сотрудники имеют первичный ключ и атрибуты сотрудника.
таблица сотрудников:
- идентификатор сотрудника
- атрибуты сотрудника
- …
Нужен ли адресу первичный ключ — это другой вопрос. Но, если вы затем захотите предоставить сотруднику дополнительный атрибут «address», который находится в отдельной таблице, я бы сначала подумал о добавлении внешнего ключа в таблицу адресов, чтобы указать, какому сотруднику принадлежит этот адрес:
адресная таблица:
- идентификатор сотрудника
- атрибуты адреса
- …
Обратите внимание, что теперь у сотрудника может быть несколько адресов, но два сотрудника не могут использовать один и тот же адрес.
Если вы хотите, чтобы несколько сотрудников использовали один и тот же адрес, вы могли бы, например, ввести первичный ключ в таблицу адресов и использовать промежуточную таблицу:
адресная таблица:
- идентификатор адреса
- атрибуты адреса
- …
таблица employee_address:
- идентификатор сотрудника
- идентификатор адреса
В этом случае оба поля в таблице employee_address являются внешними ключами. Не имеет смысла, что это будут первичные ключи. Здесь, я думаю, вы согласитесь, первичные ключи находятся в таблицах employee и address .
Тогда, отвечая на ваш первоначальный вопрос, я бы, естественно, поместил первичный ключ сотрудника в таблицу адресов, чтобы показать, что адрес принадлежит сотруднику. Но это может быть не так просто. Вы должны учитывать варианты использования, например, имеют ли два сотрудника один и тот же адрес и могут ли сотрудники иметь несколько адресов. Или у сотрудников может не быть адреса, или у адреса может не быть сотрудников?
Ответ №2:
Вы не упоминаете конкретную базу данных, поэтому в этом ответе предполагается, что она реализует возможность переноса ограничений.
Если вы абсолютно уверены, что отношение взаимно однозначное, то одним из самых чистых решений является совместное использование значения первичного ключа и убедитесь, что вы установили два симметричных внешних ключа (от сотрудника к адресу и от адреса к сотруднику).
Employee
EmployeeId (PK) (FK)
EmployeeName
Address
AddressId (PK) (FK)
AddressLine1
Чтобы вставлять, обновлять или изменять данные, оба FK должны быть отложены. Отсрочка — это стандартная функция SQL, которую, как я знаю, по крайней мере, реализуют PostgreSQL и Oracle.
Если вы хотите пойти еще дальше, имя ПК в address
таблице может быть EmployeeId
вместо AddressId
, чтобы подчеркнуть, что это одно и то же.
Комментарии:
1. Другой подход заключается в том, чтобы просто встроить поля адресов в
Employee
таблицу — это единственный способ гарантировать требуемые1:1
связи в системах, которые не поддерживают переносимые ограничения, без использования таких трюков, какVIEW
s .2. @Dai Верно, если только каждая таблица (employee и address) не имеет своих собственных отношений с другими таблицами. Если они становятся единой таблицей, то все отношения объединяются в единую супер-сущность, что может быть или не быть желательным. Но да, если нет возможности отсрочки, это, вероятно, лучший вариант.
3. Я очень расстраиваюсь из-за сложности и нелогичности, связанных с моделированием бизнес-данных / данных домена и отношений в базах данных SQL, теперь, когда я был избалован такими языками, как Rust и TypeScript, которые позволили мне написать краткий и чрезвычайно выразительный код, а также проверить правильность — но верно обратноес реляционными базами данных: я не видел каких-либо фундаментальных улучшений в способности моделирования данных (помимо отложенных ограничений). Этого почти достаточно, чтобы я захотел уйти и написать свой собственный сервер базы данных хранилища объектов…
4. @TheImpaler не могли бы вы взглянуть на свой ответ с ответом Кази? Он предположил, что одной таблицы должно быть достаточно, в то время как вы и Dai также предлагаете иметь 2 таблицы с отложенным FK.
5. @AnonymousProgrammer Оба подхода (одна таблица. против нескольких таблиц) допустимы — мы не можем сказать, какой подход лучше другого, не зная больше о требованиях вашего приложения и проекта (а также пытаясь предвидеть вероятные будущие проектные решения).
Ответ №3:
Для взаимно однозначного отношения нет причин иметь несколько таблиц. Добавьте столбец address и AddressLine1 в таблицу Employee, как показано ниже.
Employeeid (PK) Employeeename Адрес AddressLine1
Это упростит ваш дизайн и дизайн пользовательского интерфейса. И взаимно однозначное отношение будет принудительно поддерживаться без каких-либо ограничений.
Комментарии:
1. Что, если у меня много взаимно однозначных отношений, не будет ли добавлена основная таблица со многими столбцами?
2. @AnonymousProgrammer Нет такого понятия, как «слишком много столбцов», если вы не скажете нам, что означает «слишком много».
3. @AnonymousProgrammer Я видел приложения HR с 50 столбцами в таблице Employee вместе со многими отношениями «один ко многим». И это приложение работает бесперебойно в более чем 40 средних и крупных компаниях.
4. У меня также есть таблица из 500 столбцов, а размер этой таблицы составляет 2,8 терабайта. У меня все работает нормально. Итак, ваша цель покажет вам, как вы должны поддерживать свою таблицу. Но слишком много ненужных таблиц может увеличить сложность.
5. @Dai Я не совсем уверен, что «слишком много» — это сколько, потому что я никогда раньше не сталкивался с огромной базой данных. Я просто предположил, что слишком много столбцов может вызвать проблемы с производительностью, а также моя предыдущая практика — это то, что я показал в вопросе, это плохая практика??