Pytanie Definiowanie wielu kluczy obcych w jednej tabeli na wiele tabel


Mam 3 modele:

Stanowisko:

  • ID
  • tytuł
  • ciało

Zdjęcie:

  • ID
  • ścieżka pliku

Komentarz:

  • ID
  • post_id
  • ciało

i odpowiednie tabele w DB. Teraz, jeśli chcę mieć komentarze tylko do moich postów, mogę po prostu dodać następujący klucz obcy: ALTER TABLE comment ADD FOREIGN KEY (post_id) REFERENCES post (id). Ale chcę mieć komentarze do innych modeli (zdjęcie, profil, wideo itp.) I zachować wszystkie komentarze jeden stół. Jak mogę zdefiniować klucze obce (zdecydowanie potrzebuję FK dla ORM) w takim przypadku?


12
2017-10-29 09:54


pochodzenie




Odpowiedzi:


Możesz to zrobić:

 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

Nadal istnieje możliwość komentarza, który należy do dwóch różnych pozycji. Jeśli uważasz, że to był problem, mogę spróbować ulepszyć projekt.


9
2017-10-29 09:59



Nie, możliwość komentowania kilku podmiotów nie stanowi problemu. Więc potrzebuję N tabel dla N podmiotów? Czy reguły CASCADE będą działać w tym przypadku? - galymzhan
To wszystko, N tabel jest ideą tego projektu. Jeśli DMBS je obsługuje, zasady kaskadowe powinny z pewnością działać. - Álvaro González
Dzięki za wyjaśnienia. Prawdopodobnie wybiorę twoje podejście. Co masz na myśli mówiąc o ulepszaniu projektu? - galymzhan
Miałem na myśli: wymyślić jakiś sposób, aby fizycznie uniemożliwić komentarz # 123 należy do post # 456 i zdjęcie # 789 - Álvaro González
1. To jest właściwa metoda. Wiele: wiele relacja na poziomie logicznym realizowany jest jako asocjacyjny stół na poziomie fizycznym. Wiele tabel ma charakter znormalizowanej bazy danych; połączenia nie "kosztują" niczego. - PerformanceDBA


Znajdź coś wspólnego z postem, profilem itp. - użyłem Entity z braku lepszego słowa, a następnie podtypu.

  • W tym modelu jeden podmiot może mieć wiele komentarzy, jeden komentarz należy tylko do jednego podmiotu.

alt text


9
2017-10-29 11:50



To dobrze ogólny technika projektowania. GDYBYte cztery jednostki mają wspólne kolumny i można je znormalizować do postaci nadnaturalnej, to jest awans; JEŚLI NIEjest to utrudnienie (np. brak zwykłych komentarzy) z dodatkowymi wymaganymi definicjami (np. uniemożliwienie profilom posiadania komentarzy). Tj., Rozwiązujesz problem, który nie został opublikowany. - PerformanceDBA
Mam wiele komentowalnych encji i nie mają wspólnych właściwości. Tak więc mój supertable Entity będzie miał tylko kolumnę EntityId, co moim zdaniem nie jest dobrym projektem. Dlatego podejście Alvaro jest dla mnie bardziej istotne. - galymzhan


Jeśli chcesz wiedzieć, czy możesz mieć wiele kluczy obcych w pojedynczej kolumnie, odpowiedź brzmi "nie".

Jeśli chcesz, możesz mieć oddzielne klucze obce. Więc możesz zmodyfikować tabelę komentarzy w ten sposób -

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

Będziesz musiał dopilnować, aby w tabelach komentarzy były dozwolone wartości null w kolumnach PostID, PhotoID i ProfileID, a także prawdopodobnie ustawić domyślną wartość na null.

Oto DDL, aby to osiągnąć -

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

2
2017-10-29 10:13



1. To nie jest znormalizowane. 2. Nawet jeśli odłożyłeś sprawę niezormowaną, to nie zadziała. Kiedy jeden FK jest prawdziwy, pozostałe są fałszywe. Zezwolenie na wartości Null na indeksowanych polach zabija wydajność. I oczywiście istnieją znormalizowane rozwiązania, które nie mają takich problemów. - PerformanceDBA
tak, to nie jest znormalizowane. I tak, to zadziała. I owszem, być może nie najlepsza pod względem wydajności. Ale pracujemy z pewnymi ograniczeniami, jak - 1. galymzhan, w swoim pytaniu mówi, że chce wszystkich komentarzy w jednej tabeli. 2. Klucze obce są ograniczeniami, a nie indeksami. Nie istnieje żaden niejawny indeks utworzony w polach klucza obcego. - pavanred
Nie, nie będzie działać w żadnej bazie danych ANSI SQL, spróbuj przed wysłaniem. Nie możesz mieć wartości zerowej FK. Ja, podobnie jak wiele innych, dałem OP pojedynczą tabelę komentarzy; Nie w tym rzecz. Twoja odpowiedź jest nie znormalizowana, a zatem ma poważne ograniczenia i problemy z wydajnością; że jest problem. Jeśli chcesz to wykonać, opublikuj nowe pytanie. - PerformanceDBA
Używam serwera SQL Server 2008. Próbowałem go. Czek stackoverflow.com/questions/4057540/...  Zgadzam się, że nie jest on znormalizowany i miałby wpływ na wyniki. - pavanred
Problem z Ego? :) - Alexandre Bourlier


W takim przypadku możesz dodać pole ENUM, które będzie zawierało "zdjęcie", "profil" ... To będzie druga część klucza obcego


0
2017-10-29 10:01



Czy możesz to wyjaśnić? Jak wygląda Post Table? - galymzhan


Ponieważ komentarze do zdjęć to nie to samo, co komentarze do postów, przechowuję je w oddzielnych powiązanych tabelach. Tak bym miał:

Stanowisko:

  • PostId
  • tytuł
  • ciało

Wyślij komentarz:

  • Commentid
  • ciało post_id

Zdjęcie:

  • Numer identyfikacyjny fotografii
  • ścieżka pliku

PhotoComment:

  • Commentid
  • Numer identyfikacyjny fotografii
  • ciało

Używanie identyfikatora jako nazwy twojego PK jest kiepską praktyką, znacznie utrudnia raportowanie i znacznie częściej nieumyślnie dołącza do niewłaściwej tabeli w złożonym zapytaniu. Jeśli użyjesz tablenameID i konsekwentnie użyjesz tej samej nazwy dla Fks, łatwiej będzie też zobaczyć relacje.


0
2017-10-29 13:37



Zgadzam się na złe nazewnictwo kolumn. Ale zgłoszenie jest wprost przeciwne do żądania, którym jest Normalizacja komentarzy. - PerformanceDBA