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

Hvad er måden at designe en simpel lærer-fag-elev-batch relationsdatabase på?

Du mangler en tabel, der forbinder fag og elever (pkt. 2):

// elev [student_id] tager emne [subject_id]takes(student_id, subject_id) 

Bemærk, at hver basistabel har en tilknyttet udsagnsskabelon til udsagn om forretningssituationen, parametreret af kolonnenavne - dens (karakteristiske) prædikat . De rækker, der gør prædikatet sandt, går i tabellen. Bemærk, at tabeldefinitionen ligner en stenografi for prædikatet.

// lærer [id] navngivet [navn] med e-mail [email] underviser i emne [emne_id]lærer(id, navn, e-mail, emne_id)// emne [id] med navn [navn] er [beskrivelse] emne(id, navn, beskrivelse)// elev [id] navngivet [navn] bor på [sted]) elev(id, navn, sted)// batch [id] på mødested [sted] blev undervist af lærer [teacher_id] på dato [date]batch(id, venue, teacher_id, date)// elev-batch [id] rapporterer, at elev [student_id] er i batch [batch_id]student-batch(id, student_id, batch_id)// CHECK elev [student_id] ] tager det fag, der undervises af underviseren i batch [batch_id]

Da du virker i tvivl om dette, vil jeg udlede det med hensyn til, hvordan vi kan begrunde tabel-, begrænsnings- og forespørgselsdesign. En måde at udtrykke den begrænsning, du ønsker, synes at være den kommenterede CHECK ovenfor.

For at udtrykke enhver tabel, begrænsning eller forespørgsel i SQL beslutter vi først dets prædikat. Så kan vi konvertere prædikatet til stenografi. Så kan vi konvertere stenografien til SQL.

Prædikat:

elev [student_id] tager det fag, der undervises i af læreren i batch [batch_id] 

Brug af basistabelprædikater:

FOR NOGLE k.*, t.*, b.* ( student_id =k.student_id AND batch_id =b.bidAND elev [k.student_id] tager emnet [k.subject_id]AND teacher [t.id] ] navngivet [t.name] med e-mail [t.email] underviser i emne [t.subject_id] OG batch [b.id] på venue [b.venue] blev undervist af lærer [b.teacher_id] på dato [b.date] ]AND [k.subject_id] =[t.subject_id]AND [t.id] =[b.teacher_id]) 

Brug af stenografier:

FOR NOGLE k.*, t.*, b.* ( student_id =k.student_id AND batch_id =b.bidAND takes(k.student_id, k.subject_id)AND teacher(t.id, t. navn, t.e-mail, t.subject_id)AND batch(b.id, b.venue, b.teacher_id, date)AND k.subject_id =t.subject_idAND t.id =b.teacher_id) 

I en FROM repræsenterer hvert (muligvis implicit) alias en tabel som det givne basistabelnavn og/eller underforespørgsel, men med hver kolonne i sin værdi og prædikat omdøbt til alias .kolonne .

Vi får de rækker, der opfylder AND af to prædikater ved at JOINKE prædikaternes tabeller i SQL. Hvis vi vil have rækker, der opfylder AND i en betingelse, bruger vi ON eller WHERE i SQL.

En SELECT-sætning returnerer rækker, hvor FOR NOGLE værdier af stiplede kolonner er de returnerede (udokkede) kolonner lig med funktioner af stiplede kolonner, der opfylder FROM-prædikatet.

SQL:Erstat sætninger med deres tabeller, OG med JOIN eller ON eller WHERE, og outer FOR SOME &THERE EXISTS med SELECT:

SELECT t.student_id AS student_id, b.bid AS batch_idFROM tager k JOIN lærer t JOIN batch bWHERE k.subject_id =t.subject_idAND t.id =b.teacher_idAND student_id =t.student_idAND batch_id =b.id  

Tabellen med rækker, der opfylder OR for to prædikater, er UNION af deres tabeller. For OG IKKE bruger vi EXCEPT (aka MINUS) (eller et LEFT JOIN formsprog). FOR NOGLE ELLER DER EKSISTERER over alle kolonner kan ikke forespørges i SQL, men hvis vi vil vide, om der er rækker, der opfylder et prædikat, kan vi bruge EXISTS omkring en underforespørgsel med det prædikat.

Antag, at vi ønsker at begrænse en basistabel, så hver række opfylder et prædikat på nogle kolonner. Dvs. FOR ALLE kolonner HVIS de opfylder grundprædikatet SÅ opfylder de forespørgselsprædikatet. Dvs. FOR ALLE kolonner HVIS rækken de danner er i basen, SÅ er den i forespørgslen. Så vi kræver i SQL, at det IKKE EKSISTERER (VÆLG kolonner FRA basis UNDTAGET forespørgsel). Eller for hver række i basen, vi kræver i SQL, der EKSISTERER(forespørgsel).

I Standard SQL kan du CREATE ASSERTION CHECK(EKSISTERER IKKE (SELECT student_id, batch_id FROM student-batch EXCEPT query)) eller i en CREATE TABLE elev-batch kunne du CHECK(EXISTS(query)). Desværre understøttes disse ikke af MySQL eller de fleste DBMS'er. Hvis du INDSÆTTER til elev-batch efter batch, kan du ved trigger kræve, at EXISTS(query). Eller du kan tilføje bestemte kolonner og sammensatte FK (fremmednøgle) begrænsninger.

Nu skriver vi en forespørgsel. Vi vil have rækker, hvor:

FOR k.*, t.*, b.*, s.*, sb.* ( batch =b.id OG lærer =t.navn OG elev =s.nameAND takes(k.student_id, k.subject_id)AND teacher(t.id, t.name, t.email, t.subject_id)AND batch(b.id, b.venue, b.teacher_id, b.date)AND elev(s.id, s) .name, s.location)AND student-batch(sb.id, sb.student_id, sb.batch_id)AND k.subject_id =t.subject_idAND t.id =b.teacher_idAND s.id =k.student_idAND sb.student_id =k.student_idAND sb.batch_id =b.idAND @date =b.date)

Dette ligner begrænsningsprædikatet med forskellige returkolonner og tilføjede linjer. SQL'en er lige så direkte oversat. Vi tilføjer en joinforbindelse med studerende for at få elevnavne. Vi tilføjer en joinforbindelse med elev-batch, fordi begrænsningen ikke håndterer det; konteksterne, der bruger begrænsningsforespørgslen, kontrollerer, om elev-batch (student_id, batch_id) underrækker er i den.

VÆLG b.id AS batch, t.name AS lærer, s.name AS elevFRA tager k JOIN lærer t JOIN batch b JOIN elev s JOIN elev-batch sbWHERE ... OG @dato =dato 

Du kan prøve en ON-version:

VÆLG b.id AS Batch, t.name AS Teacher, s.name AS StudentFROM tager kJOIN lærer t ON k.subject_id =t.subject_idJOIN batch b ON t.id =b.teacher_idJOIN ...HVOR @dato =b.dato


  1. Sådan fremhæves poster eller værdier i en Microsoft Access-rapport ved hjælp af betinget formatering

  2. SELECT-listen er ikke i GROUP BY-sætning og indeholder ikke-aggregeret kolonne .... inkompatibel med sql_mode=only_full_group_by

  3. Apostrof og kolon i smukke links

  4. hvis tabellen ikke eksisterer, udfør en lang forespørgsel