Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Schemat bazy danych dla książek, autorów, wydawców i użytkowników z półkami na książki

Będziesz potrzebować linku N:M między books i authors , ponieważ książka może mieć wielu autorów, a każdy autor mógł napisać więcej niż jedną książkę. W RDBMS oznacza to, że będziesz potrzebować written_by tabela.

Link między books i publishers jednak jest inaczej. Każda dana książka może mieć tylko jednego wydawcę (chyba że w Twoim systemie różne wydania książki są uważane za tę samą książkę). Wszystko, czego potrzebujesz, to publisher_id klucz obcy w books

Na koniec, a co najważniejsze, patrzysz na czytelników/użytkowników. I ich stosunek do książek. Oczywiście jest to również relacja N:M. Mam nadzieję, że ludzie przeczytają więcej niż jedną książkę (wszyscy wiemy, co się stanie, jeśli przeczytasz tylko jedną...) i na pewno książkę czyta więcej niż jedna osoba. To wymaga book_users tabela połączeń. Prawdziwe pytanie brzmi:jak to zaprojektować. Istnieją trzy podstawowe projekty.

  1. Oddziel tabele według typu relacji . (jak opisuje @just_somebody ) Zalety:Masz tylko WSTAWKI i USUWANIA, nigdy AKTUALIZACJA. Chociaż wygląda to całkiem fajnie i nieco pomaga w optymalizacji zapytań, przez większość czasu nie służy to żadnemu celowi poza pokazywaniem dużego wykresu bazy danych.

  2. Jedna tabela ze status wskaźnik . (zgodnie z opisem @Hardcoded) Zalety:Masz tylko jeden stół. Wady:Będziesz mieć WSTAWKI, AKTUALIZACJE i USUNIĘCIA - coś, co RDBMS może z łatwością obsłużyć, ale ma swoje wady z różnych powodów (więcej o tym później) Również pojedynczy status to pole oznacza, że ​​jeden czytelnik może mieć tylko jedno połączenie z książką w danym momencie, co oznacza, że ​​może znajdować się tylko w plan_to_read , is_reading lub has_read status w dowolnym momencie i przyjmuje kolejność w czasie, gdy to się stanie. Jeśli ta osoba kiedykolwiek zamierzała przeczytać to ponownie , lub wstrzymać, a następnie ponownie przeczytać od początku itp., taka prosta seria wskaźników stanu może łatwo się nie powieść, ponieważ nagle ta osoba is_reading teraz, ale także has_read rzecz. W przypadku większości aplikacji jest to nadal rozsądne podejście i zwykle istnieją sposoby na zaprojektowanie pól stanu tak, aby wzajemnie się wykluczały.

  3. Dziennik . WSTAWIASZ każdy status jako nowy wiersz w tabeli - ta sama kombinacja książki i czytnika pojawi się więcej niż raz. WSTAWIASZ pierwszy wiersz z plan_to_read i sygnaturę czasową. Kolejny z is_reading . Potem kolejny z has_read . Zalety:Będziesz musiał tylko WSTAWIĆ wiersze, a otrzymasz zgrabną chronologię wydarzeń. Wady:Połączenia krzyżowe muszą teraz radzić sobie z dużo większą ilością danych (i być bardziej złożone) niż w prostszych metodach opisanych powyżej.

Możesz zadać sobie pytanie, dlaczego w jakim scenariuszu kładzie się nacisk na WSTAWIANIE, AKTUALIZOWANIE lub USUWANIE? Krótko mówiąc, za każdym razem, gdy uruchamiasz instrukcję UPDATE lub DELETE, jest bardzo prawdopodobne, że w rzeczywistości przegrasz dane. W tym momencie musisz zatrzymać się w procesie projektowania i pomyśleć „Co tu tracę?” W takim przypadku tracisz chronologiczną kolejność wydarzeń. Jeśli to, co użytkownicy robią ze swoimi książkami, jest centrum Twojej aplikacji, możesz bardzo dobrze zebrać jak najwięcej danych. Nawet jeśli w tej chwili nie ma to znaczenia, jest to rodzaj danych, które mogą później pozwolić na „magiczne” działanie. Możesz dowiedzieć się, jak szybko ktoś czyta, ile prób musi dokończyć książki itp. Wszystko to bez pytania użytkownika o dodatkowe informacje.

Tak więc moja ostateczna odpowiedź to właściwie pytanie:

Edytuj

Ponieważ może nie być jasne, jak będzie wyglądał dziennik i jak będzie działał, oto przykład takiej tabeli:

CREATE TABLE users_reading_log (
  user_id INT,
  book_id INT,
  status ENUM('plans_to_read', 'is_reading', 'has_read'),
  ts TIMESTAMP DEFAULT NOW()
)

Teraz, zamiast aktualizować tabelę „user_read” w zaprojektowanym schemacie za każdym razem, gdy zmienia się status książki, WSTAWIASZ te same dane do dziennika, który teraz wypełnia chronologię informacji:

INSERT INTO users_reading_log SET 
  user_id=1,
  book_id=1,
  status='plans_to_read';

Kiedy ta osoba zacznie czytać, wstawiasz kolejną wstawkę:

INSERT INTO users_reading_log SET 
  user_id=1,
  book_id=1,
  status='is_reading';

i tak dalej. Teraz masz bazę danych „zdarzeń”, a ponieważ kolumna sygnatury czasowej automatycznie się zapełnia, możesz teraz stwierdzić, co się stało i kiedy. Należy pamiętać, że ten system nie gwarantuje, że istnieje tylko jeden element „czy_czyta” dla określonej pary książek użytkownika. Ktoś może przestać czytać, a później kontynuować. Twoje połączenia będą musiały to uwzględnić.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać min max i avg z tabeli w mysql z różnymi wierszami?

  2. Przewodnik po projektowaniu bazy danych dla systemu zarządzania pracownikami w MySQL

  3. mysql Błąd krytyczny:nie można przydzielić pamięci dla puli buforów

  4. Nadpisywanie danych w tabeli MySQL

  5. mysql_fetch_array nie pobiera wszystkich wierszy