Projekt logiczny

Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów, etc. w oparciu o zdefiniowany diagram ERD

Finalny diagram ERD

Schemat bazy

Słowniki danych

  1. categories
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • root_id – domyślnie null, liczba całkowita
    • lft – domyślnie null, liczba całkowita
    • rgt – domyślnie null, liczba całkowita
    • level – domyślnie null, liczba całkowita
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  2. category_data
    • owner_id – not null, liczba całkowita nieujemna, domyślnie 0
    • lang – not null, ciąg znaków mniejszy od 3, domyślnie ciąg pusty, utf8
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • name – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  3. items
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • category_id – domyślnie null, liczba całkowita nieujemna
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  4. item_data
    • owner_id – not null, liczba całkowita nieujemna, domyślnie 0
    • lang – not null, ciąg znaków mniejszy od 3, domyślnie ciąg pusty, utf8
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • name – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  5. properties
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • property_group_id – domyślnie null, całkowita liczba nieujemna
    • created_at datetime – not null, data+czas
    • updated_at datetime – not null, data+czas
  6. property_data
    • owner_id – not null, liczba całkowita nieujemna, domyślnie 0
    • lang – not null, ciąg znaków mniejszy od 3, domyślnie ciąg pusty, utf8
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • name – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  7. property_groups
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • category_id – domyślnie null, całkowita liczba nieujemna
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  8. property_group_data
    • owner_id – not null, liczba całkowita nieujemna, domyślnie 0
    • lang – not null, ciąg znaków mniejszy od 3, domyślnie ciąg pusty, utf8
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • name – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  9. property_values
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • property_id – domyślnie null, całkowita liczba nieujemna
    • item_id – domyślnie null, całkowita liczba nieujemna
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  10. property_value_data
    • owner_id – not null, liczba całkowita nieujemna, domyślnie 0
    • lang – not null, ciąg znaków mniejszy od 3, domyślnie ciąg pusty, utf8
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • value – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  11. revisions
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • user_id – domyślnie null, liczba całkowita nieujemna
    • rev_no – domyślnie null, liczba całkowita nieujemna
    • is_head – domyślnie null, liczba całkowita
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  12. revision_ratings
    • revision_id – not null, liczba całkowita nieujemna, domyślnie 0
    • user_id – not null, liczba całkowita nieujemna, domyślnie 0
    • rating – domyślnie null, liczba całkowita
    • created_at – not null, data+czas
    • updated_at – not null, data+czas
  13. users
    • id – not null, unique, autoinkrementacja, liczba całkowita nieujemna
    • fb_id – domyślnie null, liczba całkowita nieujemna
    • username – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • password_salt – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • password_hash – ciąg znaków mniejszy od 33, domyślnie null, utf8
    • created_at – not null, data+czas
    • updated_at – not null, data+czas

Analiza zależności funkcyjnych i normalizacja tabel

Wszystkie tabeli w bazie danych spełniają warunku pierwszej postaci normalnej 1NF, gdyż każda z nich:

  • opisuje jeden obiekt,
  • wartości atrybutów są elementarne,
  • nie zawiera kolekcji,
  • posiada klucz główny,
  • posiada wiersze, których kolejność jest dowolna

Relacja jest w drugiej postaci normalnej wtedy i tylko wtedy gdy jest w pierwszej postaci normalnej i każda kolumna zależy funkcyjnie od całego klucza głównego (a nie np. od części klucza).

W pierwszej kolejności można sprawdzić, czy każda kolumna zależy od klucza prostego (całego klucza dla danej tabeli). Ten warunek spełniają tabele: categories, items, properties, property_groups, property_values, revisions, users

Kolumny w tabelach posiadających klucze złożone (owner_id, lang, revision_id) zależą funkcyjnie od całego klucza głównego. Na przykład każda z kolumn w tabeli category_data zależy od id kategorii (owner_id), języka (lang) oraz wersji (revision_id). Do tabel spełniających ten warunek należą: category_data, item_data, property_data, property_group_data, property_value_data

Tabela revision_ratings również jest w drugiej postaci normalnej.

Baza danych jest w trzeciej postaci normalnej 3NF, gdy jest w 2NF oraz wszystkie niekluczowe pola zależą tylko od atrybutów kluczowych (nie ma przechodnich zależności).

W szczególności dla tabel *_data, atrybut name lub value znajdujące się w każdej z nich, tyczy się danego typu (np. kategorii) i zależy tylko od klucza głównego. W tabeli categories atrybuty opisują położnie kategorii w jednym z drzew (podgrup) kategorii i zależą również tylko od klucza, jakim jest id kategorii. Tabele items, properies, property_groups, property_values mają podobną strukturę, posiadają atrybuty będące kluczami głównymi i obcymi. Są to pomocnicze tabele do tworzenia w bazie danych relacji wiele do wielu. Tabela revisions posiada niekluczowe atrybuty: rev_no, is_head oraz user_id (FK), które w kolejności oznaczają numer wersji, oznaczenie, czy dana wersja jest aktualna oraz id użytkownika, który dokonał zmian w stosunku do poprzedniej wersji. Wszystkie te kolumny zależą tylko od klucza głównego. Tabela users posiada dane charakterystyczne dla użytkownika o podanym id. W tabeli ratings atrybut rating zależy w całości od klucza głównego, jakim jest numer wersji i id użytkownika.

Stworzona baza danych jest w trzeciej postaci normalnej 3NF.

Projektowanie operacji na danych

Serwis WikiItems używa biblioteki Doctrine do komunikacji z bazą danych. Z tego powodu jako twórcy strony internetowej nie jesteśmy zmuszeni do tworzenia zapytań SQL, gdyż są one generowane z kodu PHP. W projekcie zastosowano mapowanie obiektowo-relacyjne. Przykładowe zapytania do bazy danych są przedstawione i opisane poniżej:

Kod PHP:

query = Doctrine_Query::create()

→from('Model_Item i')

→leftJoin('i.Category c')

→where('i.category_id = ? OR (c.root_id = ? AND i.category_id BETWEEN ? AND ?)', array(

category→getId(),

category→getRootId(),

category→getLeftId(),

category→getRightId()

));

Wygenerowane zapytanie:

SELECT i.id, i.category_id, i.created_at, i.updated_at, c.id, c.root_id, c.lft, c.rgt, c.level, c.created_at, c.updated_at FROM items i LEFT JOIN categories c ON i.category_id = c.id WHERE (i.category_id = ? OR (c.root_id = ? AND i.category_id BETWEEN ? AND ?))

Zapytanie odnajduje wszystkie produkty, które należą do wybranej kategorii, lub podkategorii tej kategorii.

Kod PHP:

query = Doctrine_Query::create()

→from('Model_PropertyGroup pg')

→leftJoin('pg.Category c')

→where('c.root_id = ?', root→getId())

→andWhere('c.id BETWEEN ? AND ?', array(

root→getLeftId(),

root→getRightId()

))

→andWhere('c.level < ? OR c.id = ?', array(

category→getLevel(),

category→getId()

));

Wygenerowane zapytanie:

SELECT p.id, p.category_id, p.created_at, p.updated_at, c.id, c.root_id, c.lft, c.rgt, c.level, c.created_at, c.updated_at FROM property_groups p LEFT JOIN categories c ON p.category_id = c.id WHERE (c.root_id = ? AND c.id BETWEEN ? AND ? AND (c.level < ? OR c.id = ?))

Odnajduje PropertyGroups, czyli grupy właściwości/atrybutów produktów należących do wybranej kategorii. Do grupy właściwości może należeć kilka konkretnych właściwości, którym można przypisywać wartości w tabeli property_value_data. Przykładowo grupą może być rozmiar, atrybuty należące do grupy to szerokość i wysokość, natomiast ich wartości mogą być wyrażone w calach.

Wersja Alpha: http://wikiitems.org

pl/dydaktyka/ztb/2011/projekty/wiki_items/projekt_logiczny.txt · ostatnio zmienione: 2019/06/27 15:50 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0