#database #database-design
#База данных #проектирование базы данных
Вопрос:
Сценарий такой, как показано ниже:
n ownership 1
stocks <-------------------- users
n belong to n
users -----------------------> sectors
n having 1
stocks <---------------------- sectors
В моем дизайне для них используется таблица 6: T_Stocks, T_Users, T_Sectors, T_UserStocks, T_UserSectors, T_SectorStocks, но я не думаю, что это хороший дизайн. Если у вас есть какие-либо идеи по этому поводу, пожалуйста, помогите поделиться ими со мной.
Комментарии:
1. если пользователь принадлежит к сектору, может ли пользователь владеть запасом, которого нет в секторе?
2. нет, пользователь владеет запасами только с одним сектором.
Ответ №1:
Вы правы, это не очень хороший дизайн. (Извините! :P) Поскольку у каждого stock
есть только один user
владелец, вы можете просто поместить ownerId
столбец в свою stocks
таблицу. Дайте ему ограничение внешнего ключа и не забудьте указать на него индекс!! Аналогично, у каждого sector
есть только один user
, поэтому у вас также может быть userId
столбец в sectors
. (Но мне это кажется обратным; вы намеревались установить эти отношения наоборот ??)
Однако на этом этапе ввод sectorId
в stocks
нарушает нормализацию, потому что вы могли бы создать запас, пользователь которого не совпадает с пользователем его сектора. Если вас не волнует нормализация, вы можете просто молиться, чтобы у вас никогда не получилось напортачить. С другой стороны, поскольку комбинация двух вторых взаимосвязей подразумевает первую, вы могли бы просто отбросить userId
столбец на stocks
и иметь только sectorId
.
Комментарии:
1. Спасибо за идею, Пол. Прошу прощения за ошибку в моем вопросе, я просто изменил отношение между пользователями и секторами на n: n.
Ответ №2:
Если пользователи могут владеть запасами только в секторах, в которых они участвуют, то, возможно, пересечение секторов с пользователями (n: m) на самом деле не обязательно. Может ли пользователь находиться в секторе, но не владеть запасами в этом секторе? Если пользователь находится в секторе исключительно благодаря владению акциями в этом секторе, то ваша модель немного проще. Что-то вроде этого:
SECTOR
sector_id
, name_of_sector
, ... (anything else about sectors)
STOCK
stock_id
, name_of_stock
, ... (whatever that pertains to the stock as a whole)
, sector_id -- What sector is this stock in?
STOCK_CERTIFICATE
stock_certificate_id
, stock_id -- Which stock is it?
, quantity -- number of shares, etc.
, user_id NULL -- who owns this stock, could be nobody?
USER
user_id
, user_name
, ... (anything else about the user)
Теперь, если вы хотите узнать, кому сколько принадлежит акций, вы просто посмотрите в таблицу STOCK_CERTIFICATE. Если вы хотите узнать, в каких секторах находится пользователь, вы бы использовали запрос, подобный этому:
SELECT DISTINCT
A.sector_id
, A.name_of_sector
FROM SECTOR A
INNER JOIN STOCK B
ON A.sector_id = B.sector_id
INNER JOIN STOCK_CERTIFICATE C
ON B.stock_id = C.stock_certificate_id
WHERE
C.user_id = {whatever your user ID is}
Вы также можете выполнить аналогичный distinct select в другом направлении, если хотите знать, какие пользователи находятся в данном секторе.
РЕДАКТИРОВАТЬ: Учет пользователей играет определенную РОЛЬ в секторах, к которым они принадлежат…
Если пользователи участвуют в секторах, имея роль в секторе (согласно комментарию @OP), тогда вам необходимо иметь таблицу пересечений между ПОЛЬЗОВАТЕЛЕМ и СЕКТОРОМ следующим образом…
USER_ROLE_IN_SECTOR
user_id (PK, FK)
, sector_id (PK, FK)
, role_id (PK, might be FK if you also have a ROLE table...)
Это предполагает, что пользователи могут иметь одну или несколько ролей в любом заданном секторе. Если пользователь может иметь не более одной роли в любом заданном секторе, вам придется включить уникальное ограничение на user_id sector_id. Если только один пользователь может иметь определенную роль в любом заданном секторе, тогда вам потребуется уникальное ограничение для sector_id role_id .
Эта новая таблица учитывает тот факт, что пользователи могут участвовать в секторах, фактически не владея никакими акциями в данном секторе. Другие таблицы, предложенные изначально, выше, по-прежнему являются лучшим способом записи того, кто какими акциями владеет и какие акции принадлежат каким секторам. Эта модель находится в третьей нормальной форме, поэтому нет избыточности как таковой, даже несмотря на то, что user_id и sector_id повторяются в таблице USER_ROLE_IN_SECTOR.
Вам понадобились бы ограничения другого рода, если бы вы хотели ввести бизнес-правило, в котором говорится, что пользователь не может владеть запасами в секторе, если у него нет какой-либо роли в этом секторе. Не существует чистого способа выполнить ограничение такого типа с простой ванильной ссылочной целостностью. Это такая вещь, для которой требуется проверка процедурного стиля вместо ссылочного ограничения.
Комментарии:
1. спасибо за твою идею, Джоэл! Но у пользователя есть роль в секторе, в вашем дизайне RoleId и SectorID будут повторяться много раз. Может быть сложно поддерживать согласованность.