#mysql #database #database-design
#mysql #База данных #база данных-дизайн
Вопрос:
Я разрабатываю веб-сайт для малого бизнеса (озеленение, удаление деревьев и т. Д.), принадлежащего члену семьи. Это своего рода любимый проект.
Веб-сайт позволит пользователям создавать учетную запись, а затем запрашивать услуги и создавать необходимые счета-фактуры, но также позволит члену моей семьи вводить счета-фактуры за заказы, не полученные через веб-сайт.
Я работаю над базой данных (MySQL), и в настоящее время это то, что у меня есть. Все, что содержит «User», относится к онлайн-клиентам, а все, что содержит Cust, относится к не онлайн-клиентам.
В основном то, что я пытаюсь сделать здесь, это:
У счета-фактуры есть клиент, бизнес или пользователь (онлайн-клиент). Счет-фактура также содержит одну или несколько строк счета, и каждая строка счета содержит услугу или продукт.
Я помещаю пользователей (онлайн-клиентов) в отдельную таблицу, потому что для пользователя имеет смысл иметь пароль и соль пароля (и, возможно, другие вещи), но у клиента, добавленного исключительно для ведения записей, не должно быть пароля и вещей, связанных с веб-сайтом.
ServicesAndProducts
--------------------------
| ID INT (PK) |
| Name VARCHAR(50) |
| BasePrice DECIMAL(7,2) |
| ... |
--------------------------
CustServicesProvided UserServicesProvided
--------------------------- ---------------------------
| ID INT (PK) | | ID INT (PK) |
| ServiceID INT (FK) | | ServiceID INT (FK) |
| CustInvoiceID INT (FK) | | UserInvoiceID INT (FK) |
| ... | | ... |
--------------------------- ---------------------------
CustInvoices UserInvoices
-------------------------- --------------------------
| ID INT (PK) | | ID INT (PK) |
| CustomerID INT (FK) | | UserId INT (FK) |
| .... | | .... |
-------------------------- --------------------------
Customers Users
-------------------------- ---------------------------
| ID INT (PK) | | ID INT (PK) |
| Name VARCHAR(50)) | | Name VARCHAR(50) |
| BasePrice DECIMAL(7,2) | | PasswordHash VARCHAR(50)|
| ... | | PasswordSalt VARCHAR(50)|
-------------------------- | ... |
---------------------------
У меня также есть другие похожие сервисы BusinessServicesProvided, BusinessInvoices и Business, потому что мне нужны внешние ключи, и у предприятий будут другие поля, чем у двух других.
Мой вопрос: есть ли способ объединить таблицы счетов-фактур вместе и объединить таблицы предоставляемых услуг вместе, сохраняя при этом три вида внешних ключей между таблицей счетов-фактур и клиентами и пользователями (и предприятиями)?
Я подумал о возможном добавлении таблицы InvoiceType, а затем о том, чтобы указать TypeID (FK) в таблице счетов, но я не знаю, как поддерживать внешний ключ между объектом (клиентом, бизнесом или пользователем) и счетом. например:
ServicesAndProducts
--------------------------
| ID INT (PK) |
| Name VARCHAR(50) |
| BasePrice DECIMAL(7,2) |
| ... |
--------------------------
ServicesProvided
---------------------------
| ID INT (PK) |
| ServiceID INT (FK) |
| CustInvoiceID INT (FK) |
| ... |
---------------------------
Invoices InvoiceType
-------------------------- ---------------------------
| ID INT (PK) | | ID INT (PK) |
| ForeignID INT (FK) | | Name VARCHAR(50) |
| Invoice Type INT (FK) | | |
| .... | | |
-------------------------- ---------------------------
Customers Users
-------------------------- ---------------------------
| ID INT (PK) | | ID INT (PK) |
| Name VARCHAR(50)) | | Name VARCHAR(50) |
| BasePrice DECIMAL(7,2) | | PasswordHash VARCHAR(50)|
| ... | | PasswordSalt VARCHAR(50)|
-------------------------- | ... |
---------------------------
Я также рассматривал возможность создания триггера для создания нового клиента при создании пользователя, но я также хотел бы, чтобы клиент мог просматривать счета / услуги, которые они запрашивали в прошлом.
Это мой первый опыт проектирования базы данных, поэтому любые идеи приветствуются.
Ответ №1:
Нет, вы не можете указывать внешний ключ на первичные ключи в разных таблицах, указывая базе данных найти соответствующую запись в одной из таблиц (кроме того, предположительно диапазон значений первичного ключа в разных таблицах может перекрываться, и тогда вы можете сопоставить две или более таблиц первичных ключей).
Ваша ошибка заключается в создании совершенно новой таблицы для учета различий, например, между клиентами и пользователями. Вместо этого создайте единую таблицу с общими столбцами (вероятно, называемую customer), а затем разделите таблицы с внешними ключами обратно в основную таблицу. Каждая таблица содержит столбцы для одного из подтипов клиентов (онлайн или из плоти и крови).
То же самое для разных видов счетов. Одна таблица содержит общую информацию о счете (особенно первичный ключ), а одна или несколько вспомогательных таблиц содержат информацию, относящуюся к виду счета.
Этот дизайн похож на наследование классов в объектно-ориентированном программировании.