sql >> Database teknologi >  >> RDS >> Mysql

Databaseskema for bøger, forfattere, udgivere og brugere med bogreoler

Du skal bruge et N:M-link mellem books og authors , da en bog kan have flere forfattere, og hver forfatter kan have skrevet mere end én bog. I et RDBMS betyder det, at du skal bruge en written_by tabel.

Linket mellem books og publishers er dog anderledes. Enhver given bog kan kun have én udgiver (medmindre forskellige udgaver af en bog i dit system betragtes som den samme bog). Så alt hvad du behøver her er et publisher_id fremmednøgle i books

Til sidst, og vigtigst af alt, ser du på læserne/brugerne. Og deres forhold til bøger. Dette er naturligvis også en N:M relation. Jeg håber bestemt, at folk læser mere end én bog (vi ved alle, hvad der sker, hvis man nogensinde kun læser én...) og bestemt læses en bog af mere end én person. Det kræver en book_users tilslutningsbord. Det virkelige spørgsmål her er, hvordan man designer det. Der er tre grundlæggende designs.

  1. Adskil tabeller efter type relation . (som skitseret af @just_somebody ) Fordele:Du har kun INSERTS og DELETES, aldrig OPDATERINGER. Selvom dette ser pænt ud og en del hjælper med forespørgselsoptimering, tjener det for det meste ikke noget egentligt formål ud over at vise et stort databasediagram frem.

  2. Én tabel med en status indikator . (som beskrevet af @Hardcoded) Fordele:Du har kun én tabel. Ulemper:Du vil have INSERTS, UPDATES og DELETES - noget RDBMS nemt kan håndtere, men som har sine mangler af forskellige årsager (mere om det senere) Også en enkelt status felt antyder, at én læser kun kan have én forbindelse til bogen til enhver tid, hvilket betyder, at han kun kan være i plan_to_read , is_reading eller has_read status på ethvert tidspunkt, og det forudsætter en ordre i tide, dette sker. Hvis den person nogensinde ville planlægge at læse den igen , eller pause, så genlæs fra begyndelsen osv., sådan en simpel serie af statusindikatorer kan let fejle, fordi lige pludselig den person is_reading nu, men også has_read tingen. For de fleste applikationer er dette stadig en rimelig tilgang, og der er normalt måder at designe statusfelter på, så de udelukker hinanden.

  3. En log . Du INDSÆTTER hver status som en ny række i en tabel - den samme kombination af bog og læser vil dukke op mere end én gang. Du INDSÆTTER den første række med plan_to_read , og et tidsstempel. En anden med is_reading . Så endnu en med has_read . Fordele:Du behøver kun at INDSÆTTE rækker, og du får en pæn kronologi over ting, der skete. Ulemper:Sammenføjninger på tværs af tabeller skal nu håndtere meget flere data (og være mere komplekse) end i de simplere fremgangsmåder ovenfor.

Du kan spørge dig selv, hvorfor der lægges vægt på, om du INDSÆTTER, OPDATER eller SLETTER i hvilket scenarie? Kort sagt, når du kører en UPDATE- eller DELETE-sætning, er det meget sandsynligt, at du faktisk taber data. På det tidspunkt skal du stoppe i din designproces og tænke "Hvad er det, jeg mister her?" I dette tilfælde mister du den kronologiske rækkefølge af begivenheder. Hvis det, brugerne laver med deres bøger, er centrum for din applikation, vil du måske meget gerne samle så mange data, som du kan. Selvom det ikke betyder noget lige nu, er det den type data, som måske giver dig mulighed for at lave "magi" senere hen. Du kan finde ud af, hvor hurtigt nogen læser, hvor mange forsøg de skal bruge for at færdiggøre en bog osv. Alt sammen uden at bede brugeren om ekstra input.

Så mit endelige svar er faktisk et spørgsmål:

Rediger

Da det måske ikke er klart, hvordan en log ville se ud, og hvordan den ville fungere, er her et eksempel på en sådan tabel:

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, i stedet for at opdatere "user_read"-tabellen i dit designede skema, hver gang status for en bog ændres, INDSÆTTER du nu de samme data i loggen, som nu fyldes med en kronologi af information:

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

Når denne person faktisk begynder at læse, indsætter du endnu en:

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

og så videre. Nu har du en database med "hændelser", og da tidsstemplingskolonnen automatisk fylder sig selv, kan du nu fortælle, hvad der skete hvornår. Bemærk venligst, at dette system ikke sikrer, at der kun findes én 'er_læser' for et specifikt brugerbogspar. Nogen stopper måske med at læse og fortsætter senere. Det skal dine joins tage højde for.



  1. Hvordan skal ip2long konverterede IP'er gemmes i MySQL?

  2. tælle poster, der forbinder spørgsmål og svartabeller

  3. hvordan ændres postgresql lytteport i Windows?

  4. Vis Samlingen i MariaDB