Определение нескольких внешних ключей в одной таблице для многих таблиц
У меня есть 3 модели:
Сообщение
Фото
Комментарий
и соответствующие таблицы в БД. Теперь, если я хочу иметь комментарии только для своих сообщений, я могу просто добавить следующий внешний ключ: ALTER TABLE comment ADD FOREIGN KEY (post_id) REFERENCES post (id)
. Но я хочу получать комментарии для других моделей (фото, профиль, видео и т.д.) И оставлять комментарии в таблице один. Как я могу определить внешние ключи (в частности, мне нужны FK для ORM)?
Ответы
Ответ 1
Вы можете сделать это:
post:
* post_id (PK)
* title
* body
photo:
* photo_id (PK)
* filepath
comment:
* comment_id (PK)
* body
comment_to_post
* comment_id (PK) -> FK to comment.comment_id
* post_id (PK) -> FK to post.post_id
comment_to_photo
* comment_id (PK) -> FK to comment.comment_id
* photo_id (PK) -> FK to photo.photo_id
По-прежнему существует возможность получить комментарий, относящийся к двум различным элементам. Если вы считаете, что это проблема, я могу попытаться улучшить дизайн.
Ответ 2
Найдите что-то общее для публикации, профиля и т.д. Я использовал Entity
для отсутствия лучшего слова, а затем подтипа.
- В этой модели у одного объекта может быть много комментариев, один комментарий принадлежит только одному объекту.
![alt text]()
Ответ 3
Если вы хотите знать, можете ли вы иметь несколько внешних ключей для одного столбца, тогда ответ не будет вашим.
Вы можете иметь отдельные внешние ключи, если хотите. Поэтому вы можете изменить свою таблицу комментариев так:
comment:
* comment_id (PK)
* PostID (FK to Post.PostID)
* PhotoID (FK to <Photo>.PhotoID)
* ProfileID (FK to <Profile>.ProfileID)
* Body
И вам нужно будет убедиться, что вы разрешаете нули в столбцах PostID, PhotoID и ProfileID в таблице комментариев, а также, возможно, установите значение по умолчанию равным null.
Вот DDL для достижения этого -
Create table Photo
(
PhotoID int,
PhotoDesc varchar(10),
Primary key (PhotoID)
)
Create table Post
(
PostID int,
PostDesc varchar(10),
Primary key (PostID)
)
Create table Profiles
(
ProfileId int,
ProfileDesc varchar(10),
Primary key (ProfileId)
)
Create table Comment
(
CommentID int,
PhotoID int,
PostID int,
ProfileId int,
body varchar(10),
Primary key (CommentID),
Foreign key (PhotoID) references Photo(PhotoID),
Foreign key (PostID) references Post(PostID),
Foreign key (ProfileId) references Profiles(ProfileId)
)
insert into Photo values (1,'Photo1')
insert into Photo values (2,'Photo2')
insert into Photo values (3,'Photo3')
insert into Post values (11,'Post1')
insert into Post values (12,'Post2')
insert into Post values (13,'Post3')
insert into Profiles values (111,'Profiles1')
insert into Profiles values (112,'Profiles2')
insert into Profiles values (113,'Profiles3')
insert into Comment (CommentID,PhotoID,body) values (21,1,'comment1')
insert into Comment (CommentID,PhotoID,body) values (22,3,'comment2')
insert into Comment (CommentID,PostID,body) values (23,11,'comment3')
insert into Comment (CommentID,PostID,body) values (24,12,'comment4')
insert into Comment (CommentID,ProfileId,body) values (25,112,'comment5')
insert into Comment (CommentID,ProfileId,body) values (26,113,'comment6')
-- to select comments seperately for Photos, profiles and posts
select * from Comment where PhotoID is not null
select * from Comment where ProfileId is not null
select * from Comment where PostID is not null
Ответ 4
В этом случае вы можете добавить поле ENUM, которое будет содержать "фото", "профиль"... Это будет вторая часть внешнего ключа
Ответ 5
Поскольку комментарии к фотографии - это не то же самое, что и комментарии к сообщениям, я бы сохранил их в отдельных связанных таблицах. Поэтому у меня было бы:
Сообщение:
- сообщения дан
- название
- Тело
PostComment:
Фото:
PhotoComment:
Плохая практика использования идентификатора как имени вашего ПК, это делает гораздо сложнее сделать отчетность и, скорее, непреднамеренно присоединиться к неправильной таблице в сложном запросе. Если вы используете tablenameID и последовательно используете одно и то же имя для Fks, тогда легче видеть отношения.