2010-10-29 7 views
12

tengo 3 modelos:La definición de varias claves externas en una mesa para muchas mesas

Pon:

  • Identificación
  • título
  • cuerpo

Foto :

  • Identificación
  • rutaarchivos

comentario:

  • Identificación
  • post_id
  • cuerpo

y tablas correspondientes en DB. Ahora, si quiero tener comentarios solo para mis publicaciones, simplemente puedo agregar la siguiente clave externa: ALTER TABLE comment ADD FOREIGN KEY (post_id) REFERENCES post (id). Pero quiero tener comentarios para otros modelos (foto, perfil, video, etc.) y mantener todos los comentarios en una tabla. ¿Cómo puedo definir claves externas (definitivamente necesito FK para ORM) en tal caso?

Respuesta

9

Usted puede hacer esto:

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 

Todavía hay la posibilidad de tener un comentario que pertenece a dos artículos diferentes. Si crees que eso sería un problema, puedo intentar mejorar el diseño.

+0

No, la posibilidad de tener comentarios en varias entidades no es un problema. Entonces, ¿necesito N tablas para N entidades? ¿Funcionarán las reglas de CASCADE en este caso? – galymzhan

+1

Eso es todo, N tablas es la idea de este diseño. Si el DMBS los admite, las reglas de cascada deberían funcionar. –

+0

Gracias por las explicaciones. Probablemente elegiré tu enfoque. ¿Qué quiso decir con mejorar el diseño? – galymzhan

0

En ese caso, se puede añadir un campo ENUM que contendrá 'foto', 'perfil' ... Será la segunda parte de la clave externa

+0

¿Podría explicarlo? ¿Cómo se ve la tabla de publicaciones? – galymzhan

2

Si usted quiere saber si puede tener múltiples claves externas a una sola columna, entonces la respuesta es no, no puedes.

Puede tener claves externas separadas si lo desea. Por lo que su puede modificar su mesa comentario como este -

comment: 
    * comment_id (PK) 
    * PostID (FK to Post.PostID) 
    * PhotoID (FK to <Photo>.PhotoID) 
    * ProfileID (FK to <Profile>.ProfileID) 
    * Body 

Y, usted tendrá que asegurarse de que usted permita valores nulos en columnas PostID, PhotoID y profileId en la tabla comentario y quizá también establece el valor predeterminado en nulo.

Aquí es el DDL para lograr esto -

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 
+0

1. Eso no está normalizado. 2. Incluso si deja de lado el problema no normalizado, no funcionará.Cuando un FK es verdadero, los otros son todos falsos. Permitir nulos en los campos indexados mata el rendimiento. Y, por supuesto, hay soluciones normalizadas que no tienen tales problemas. – PerformanceDBA

+0

sí, no está normalizado. Y, sí, funcionará. Y sí, quizás no sea el mejor en cuanto a rendimiento. Pero estamos trabajando bajo ciertas limitaciones como: 1. galymzhan, en su pregunta dice que quiere todos los comentarios en una sola tabla. 2. Las claves externas son restricciones y no índices. No hay un índice implícito creado en campos de claves externas. – pavanred

+0

No, no funcionará en ninguna base de datos SQL ANSI, pruébelo antes de publicarlo. No puedes tener un FK nulo. Yo, al igual que muchos otros, le he dado a OP una sola tabla de Comentarios; Ese no es el problema. Su respuesta no está normalizada, y tiene graves limitaciones y problemas de rendimiento; ese * es * el problema. Si desea llevar esto adelante, publique una nueva pregunta. – PerformanceDBA

9

Encontrar algo común para publicar, perfil, etc - Me han utilizado Entity por la falta de una mejor palabra, entonces subtipo.

  • En este modelo, una entidad puede tener muchos comentarios, un comentario pertenece a una sola entidad.

alt text

+0

Esa es una buena técnica de diseño * genérico *. ** SI ** las cuatro entidades tienen columnas comunes, y se pueden normalizar en un supertipo, es un avance; ** SI NO **, es un obstáculo (por ejemplo, no hay comentarios comunes) con definiciones adicionales requeridas (por ejemplo, no permitir que los perfiles tengan comentarios). Es decir, estás resolviendo un problema que no se publicó. – PerformanceDBA

+0

Tengo muchas entidades commentables y no tienen propiedades comunes. Por lo tanto, mi Entidad supertable tendrá solo la columna EntityId, que creo que no es un buen diseño. Es por eso que el enfoque de Alvaro es más relevante para mí. – galymzhan

0

Desde comentarios de las fotos no son las mismas cosas que colocar los comentarios, me almacenarlos en tablas relacionadas separados. Así que tendría que tener:

la publicación:

  • postID
  • título
  • cuerpo

PostComment:

  • Commentid
  • post_id b ody

Foto:

  • photoid
  • rutaarchivos

PhotoComment:

  • Commentid
  • photo_id
  • cuerpo

Es una mala práctica de utilizar ID que el nombre de su PK, que hace que sea mucho más difícil de hacer informes y mucho más propensos a unirse de forma inadvertida a la mesa equivocada en una consulta compleja. Si usa tablenameID y usa constantemente el mismo nombre para Fks, entonces es más fácil ver las relaciones también.

+0

Estoy de acuerdo con la nomenclatura de la columna pobre. Pero el envío es explícitamente el opuesto de la solicitud, que es Normalizar comentarios. – PerformanceDBA

Cuestiones relacionadas