Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem w projektowaniu bazy
Forum PHP.pl > Forum > Bazy danych
quality
Witam
Napotkalem 2 problemy projektując bazę danych:

1. Mam 2 moduly - artykuly i galerie. Chcialbym zeby i galerie i artykuly mogly byc komentowane. I tutaj pytanie. Czy zrobic oddzielna tabele komentarzy dla galerii i artykulow, czy zrobic jedna tabele komentarze i dodatkowo 2 tabele "galerie -> wiele do wielu -> komentarze" i "artykuly -> wiele do wielu -> komentarze" ?

2. Drugi problem jest podobny. Mianowicie chodzi o to ze galerie, artykuly, programy itd posiadaja typy. I tutaj tez czy zrobic osobne tabele np: "typ_artykulow" itp czy zrobic jedna tabele
" typy" i dodatkowa "rodzaj_typow" (w ktorych znajda sie informacje o modulach do ktorych beda te typy nalezec)

Ps. Mam nadzieje ze nie zamotalem zabardzo. jak cos to przesle screeny z zamodelowana baza.
ddiceman
AD 1.
Nie sadze, ze funkcjonalnosc 'wiele do wielu' jest Ci potrzebna - w koncu komentarz dotyczy jednej galerii, lub jednego artykulu, wiec jest to relacja 'jeden do wielu'.
Zastanów się, czy komentarz do galerii ma strukturę taka sama, jak do artykulu. Jezeli tak - wcisnij w jedna tabele i dodaj pole TYP enum('artykul', 'galeria') czy podobne - latwiej bedziesz mogl wyciagac statystyki komentarzy uzytkownikow etc. (choc mozna robic unie, ale po co?)

AD 2.
Zalezy, czy typow masz skonczona ilosc i niezmienna, czy nie. Jezeli pierwsza mozliwosc - ENUM, albo jakis INT. Jezeli druga - lepiej tabelke. Co prawda teoria normalizacji mowi, bys w kazdej sytuacji rozbijal na 2 tabele, ale przy duzym obciazeniu serwera zmusza sie tak glowice dysku do skakania po bazie, co owocuje problemami. Ni mniej ni wiecej powiem tylko, bys sam zastanowil sie, czy potrzebujesz osobnej tabeli.
quality
Hmm jezeli tabele sa osobne lub jest jest pole enum to moze i jest relacja jeden do wielu, ale nie w takim przypadku jak ja chce zrobic.

Zrobilem zdjecia modelowanej bazy:



To jest pierwszy przypadek w dwoch wersjach.

Tabele comments maja taka sama strukture.

To jest przypadek ktory wydaje mi sie najlepszy. jednak tworzenie dodatkowych 2 tabel. Fakt ze to sa same indeksy i poprawia szybkosc dzialania ale moze jest jakis lepszy sposob o ktorym nie wiem tongue.gif. nie interesuja mnie pola enum 'artykul', 'galeria'. Ma to byc w pelni relacyjna baza danych do duzych stron, a bede sam je programowal wiec chce aby byla dobrze zamodelowana.



Ten jest za to latwiejszy w obrobce ale za to nadmiarowosc danych i nie zgodne ze standardem :/
ddiceman
Dalej nie rozumiem, czemu 'wiele do wielu'? Czy zakladasz, ze ten sam komentarz moze byc i do artykulu i do galerii? Czyli 'wow, fajna galeria' jednoczesnie przypisany i do galerii i do artykulu?

Te 2 schematy nie prezentuja tej samej funkcjonalnosci - pierwszy pozwala na to, co opisalem powyzej. Drugi zapewnia, to, czego moznaby sie spodziewac:
- do jednej galerii (artykulu) moze byc wiele komentarzy
- komentarz jest przypisany do dokladnie jednego artykulu albo zdjecia

Wiec, dla jasnosci, jezeli zalezy Ci na FK, to zrobilbym tabele COMMENTS, z polami
Kod
author,
title,
content,
date,
ip,
active,
author_id,

gallery_id_FK, /* klucz obcy wskazujacy, do ktorej galerii nalezy komentarz, null jesli do zadnej */
article_id_FK, /* klucz obcy wskazujacy, do ktorego artykulu nalezy komentarz, null jesli do zadnej */


Wg tej konstrukcji zawsze jedno z kluczy obcych musi byc NULLem a drugie nie, czyli przydalby sie wtedy trigger:

Kod
CHECK (
    (gallery_id_FK IS NULL AND article_id_FK IS NOT NULL) OR
    (gallery_id_FK IS NOT NULL AND article_id_FK IS NULL)
)


No ale na nieszczescie MySQL nie obsluguje takowych. Chyba, ze praca ma charakter dydaktyczny (a takie mam wrazenie)
quality
gallery_id_FK, /* klucz obcy wskazujacy, do ktorej galerii nalezy komentarz, null jesli do zadnej */
article_id_FK, /* klucz obcy wskazujacy, do ktorego artykulu nalezy komentarz, null jesli do zadnej */

No wlasnie o cos takiego mi dokladnie chodzilo. Po prostu nie wiem jak zrobic zeby w jednym polu bylo NULL, zeby jeden komentarz nie byl przypisywany i do artykulu i do galerii.

Sytuacja wiele do wielu po prostu omija ten problem, ale chodzi mi wlasnie o to co piszesz, nie wiem tylko jak to rozgryzc skoro jest napisales.

Nie uzywalem nigdy trigerow w sql. Mozesz cos wiecej powiedziec na ten temat ?

Dzieki z gory

Eh pokombinowalem i wyszlo ze wystarczy dac NULL w tych polach i wszystko ladnie bedzie dzialac. Martwilem sie wczesniej po prostu ze mi sie nie doda komentarz jezeli nie bedzie jednego z id (artykulu czy galeri).
Dzieki

Ale nie rozwiazalem jeszcze tego drugiego watku.
Moze pokaze model bazy bo tak latwiej zrozumiec.

Chodzi o kategorie poszczegolnych modulow. Na pierwszym zdjeciu zrobilem to za pomoca tylko 2 tabel polaczonych relacjami.
Ten sposob wydaje sie najrozsadniejszy, jednak taki model wyglada bardzo zagmatwanie. mysle ze to jest ok jednak nie jestem przekonany do konca.


To jest drugi sposob, w ktorym kategorie sa osobnymi tabelami dla kazdego z modulow

ddiceman
Triggery - jak dorbze pamietam - obecnie sa w MySQL tylko na silniku InnoDB i jezeli rzeczywiscie zalezy Ci na tym mechanizmie, to prawdopodobnie musisz to zrobic w brzydki sposob (podobno, jezeli chce sie powstrzymac MySQL przed wykonaniem zapytania, to nie da sie tego zrobic za bardzo elegancko):
  1. /* tabela w ktorej chcesz chronic pola l1, l2 */
  2. CREATE TABLE liczby1 (
  3. id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  4. l1 INT,
  5. l2 INT
  6. ) ENGINE = InnoDB;
  7.  
  8. /* tabela jedynie do sztucznego wywolywania bledow, z jedna krotka */
  9. CREATE TABLE trigger_trap(
  10. id TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY
  11. );
  12. INSERT INTO trigger_trap VALUE(1);
  13.  
  14. /* trigger */
  15. DELIMITER $$
  16. CREATE TRIGGER sprawdz_liczby BEFORE INSERT ON liczby1 FOR EACH ROW
  17. BEGIN IF (NEW.l1 IS NULL AND NEW.l2 IS NULL) OR (NEW.l1 IS NOT NULL AND NEW.l2 IS NOT NULL)
  18. THEN
  19. INSERT INTO trigger_trap VALUES (1); /* wywolanie puapki - duplikat wartosci */
  20. END IF;
  21. END $$
  22. DELIMITER ;
  23.  
  24. /* testowe kwerendy */
  25. INSERT INTO liczby1 value(NULL, NULL, 1);
  26. INSERT INTO liczby1 value(NULL, 1, NULL);
  27. INSERT INTO liczby1 value(NULL, NULL, NULL);
  28. INSERT INTO liczby1 value(NULL, 1, 1);
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.