Страницы

Поиск по вопросам

среда, 21 ноября 2018 г.

Полиморфизм в реляционных БД. Возможно ли?

Есть база данных (postgresql), содержащая три таблицы - Люди (ID, Имя, Фамилия, Отчество, Наименование), Организации (ID, Наименование, Адрес, Расчетный счет), Автомобили (ID, Марка, Модель, Пробег, Владелец). Суть проблемы: Необходимо создать связи между автомобилями и владельцами. Владельцем автомобиля может быть как человек (запись в таблице Люди), так и организация (запись в таблице Организации). Вопрос: Каким образом можно осуществить данную связь? Может ли внешний ключ быть полиморфным и, следовательно, каким образом во время JOIN узнать с какой таблицей объединятся(как хранить информацию о типе во внешнем ключе)? PS: Заранее извиняюсь за, возможно, глупый вопрос, и прошу учесть, тот факт, что с SQL и РБД как таковыми только познакомился, и есть острая необходимость решить вышеуказанную проблему в крайне короткий срок. Update: В первой версии вопроса не указал общее поле - Наименование - в случае если Владелец - человек, его Наименование - например, Иванов И.И. В качестве примера приведу вымышленный код, думаю так будет понятней:
SELECT Авто.Марка, Авто.Модель, Наименование FROM Авто INNER JOIN Авто.Внешний_ключ_владельца.Таблица ON Авто.Внешний_ключ_владельца.ID = Авто.Владелец.ID
И возможный результат: "Daewoo" "Nexia" "Иванов. И.И." "Ford" "Focus" "ООО ТОРГОПТ" "Schevrolet" "Camaro" "Сидоров С.В."


Ответ

Структура данных должна быть такой, чтобы запросы по ней были максимально простыми. Если вам в вашем запросе нужно только Наименование от владельца, то в разделении людей и организаций нет никакого смысла. Это должна быть одна таблица Владельцы. Дополнительные поля могут быть как в той же таблице, так и в дочерних типа "данные юрлиц"/"данные физлиц". Все зависит от запросов, сравните ваш вариант:
select cars.*, persons.fullname from cars join persons on cars.owner = persons.id and cars.isorg = 0 union all select cars.*, orgs.fullname from cars join orgs on cars.owner = orgs.id and cars.isorg = 1
и запрос с одной таблицей:
select cars.*, owners.fullname from cars join owners on cars.owner = owners.id
Если вам понадобятся все дополнительные поля в этом запросе (надо еще придумать как их красиво выводить в одной таблице) вы получите одни и те же данные: будут null для людей в адресе и расчетном счете, и null для фио для организаций.
Если вы планируете более сложную логику запросов (которую вы в вопросе не указали) то идите от нее. И идите путем простоты.

Комментариев нет:

Отправить комментарий