Du behöver en N:M-länk mellan books
och authors
, eftersom en bok kan ha flera författare och varje författare kan ha skrivit mer än en bok. I ett RDBMS betyder det att du behöver en written_by
bord.
Länken mellan books
och publishers
är dock annorlunda. Varje given bok kan bara ha ett förlag (såvida inte olika utgåvor av en bok i ditt system anses vara samma bok). Så allt du behöver här är ett publisher_id
främmande nyckel i books
Till sist, och viktigast av allt, tittar du på läsarna/användarna. Och deras relation till böcker. Naturligtvis är detta också en N:M relation. Jag hoppas verkligen att folk läser mer än en bok (vi vet alla vad som händer om man bara läser en...) och att en bok läses av mer än en person. Det kräver en book_users
anslutningstabell. Den verkliga frågan här är hur man designar den. Det finns tre grundläggande design.
-
Separera tabeller efter typ av relation . (som beskrivs av @just_somebody ) Fördelar:Du har bara INFOGA och TA BORT, aldrig UPPDATERINGAR. Även om det här ser ganska snyggt ut och till viss del hjälper till med frågeoptimering, tjänar det för det mesta inget annat ändamål än att visa upp ett stort databasdiagram.
-
En tabell med
status
indikator . (som beskrivs av @Hardcoded) Fördelar:Du har bara en tabell. Nackdelar:Du kommer att ha INSLAG, UPPDATERINGAR och DELETE – något som RDBMS enkelt kan hantera, men som har sina brister av olika anledningar (mer om det senare) Dessutom en endastatus
fältet innebär att en läsare bara kan ha en anslutning till boken när som helst, vilket betyder att han bara kan vara iplan_to_read
,is_reading
ellerhas_read
status vid vilken tidpunkt som helst, och det förutsätter en ordning i tid som detta händer. Om den personen någonsin skulle planera att läsa den igen , eller pausa, läs sedan om från början etc, en sådan enkel serie av statusindikatorer kan lätt misslyckas, eftersom den personen helt plötsligtis_reading
nu, men ocksåhas_read
saken. För de flesta applikationer är detta fortfarande ett rimligt tillvägagångssätt, och det finns vanligtvis sätt att utforma statusfält så att de utesluter varandra. -
En logg . Du INFOGA varje status som en ny rad i en tabell - samma kombination av bok och läsare kommer att dyka upp mer än en gång. Du INFOGA den första raden med
plan_to_read
, och en tidsstämpel. En annan medis_reading
. Sedan en till medhas_read
. Fördelar:Du behöver bara INFOGA rader, och du får en snygg kronologi över saker som hände. Nackdelar:Korstabellkopplingar måste nu hantera mycket mer data (och vara mer komplexa) än i de enklare metoderna ovan.
Du kan fråga dig själv, varför ligger det tonvikten på om du INFOGA, UPPDATERA eller TA BORT i vilket scenario? Kort sagt, när du kör en UPDATE- eller DELETE-sats är det mycket sannolikt att du faktiskt förlorar data. Då måste du stanna upp i din designprocess och tänka "Vad är det jag förlorar här?" I det här fallet förlorar du händelsernas kronologiska ordning. Om det som användarna gör med sina böcker är centrum för din applikation, kan du mycket väl vilja samla in så mycket data du kan. Även om det inte spelar någon roll just nu, är det den typ av data som kan göra att du kan göra "magi" senare. Du kan ta reda på hur snabbt någon läser, hur många försök de behöver för att avsluta en bok, etc. Allt detta utan att be användaren om någon extra input.
Så mitt sista svar är faktiskt en fråga:
Redigera
Eftersom det kanske inte är klart hur en logg skulle se ut och hur den skulle fungera, är här ett exempel på en sådan tabell:
CREATE TABLE users_reading_log (
user_id INT,
book_id INT,
status ENUM('plans_to_read', 'is_reading', 'has_read'),
ts TIMESTAMP DEFAULT NOW()
)
Nu, istället för att uppdatera tabellen "user_read" i ditt designade schema när statusen för en bok ändras, INFOGA nu samma data i loggen som nu fylls med en kronologi av information:
INSERT INTO users_reading_log SET
user_id=1,
book_id=1,
status='plans_to_read';
När den personen faktiskt börjar läsa, infogar du en annan:
INSERT INTO users_reading_log SET
user_id=1,
book_id=1,
status='is_reading';
och så vidare. Nu har du en databas med "händelser" och eftersom tidsstämpelkolumnen automatiskt fylls av sig själv kan du nu berätta vad som hände när. Observera att det här systemet inte säkerställer att det bara finns en "läser" för ett specifikt användarbokspar. Någon kanske slutar läsa och senare fortsätter. Dina anslutningar måste stå för det.