sql >> Database >  >> RDS >> Mysql

Hoe bewaar je meerdere opties in één tabel?

Lees meer over Gegevensnormalisatie , Algemene indexering concepten, en Foreign Key beperkingen om gegevens schoon te houden met referentiële integriteit. Dit zal je op weg helpen.

Het opslaan van gegevens in arrays lijkt op papier misschien natuurlijk, maar voor de db-engine zijn de prestaties meestal zonder indexgebruik. Bovendien zult u op dag 2 ontdekken dat het verkrijgen en onderhouden van uw gegevens een nachtmerrie zal zijn.

Het volgende zou je op weg moeten helpen met een goede start terwijl je aan het sleutelen bent. wordt lid ook.

create table student
(   studentId int auto_increment primary key,
    fullName varchar(100) not null
    -- etc
);

create table dept
(   deptId int auto_increment primary key,
    deptName varchar(100) not null -- Economics
    -- etc
);

create table course
(   courseId int auto_increment primary key,
    deptId int not null,
    courseName varchar(100) not null,
    -- etc
    CONSTRAINT fk_crs_dept FOREIGN KEY (deptId) REFERENCES dept(deptId)
);

create table SCJunction
(   -- Student/Course Junction table (a.k.a Student is taking the course)
    -- also holds the attendance and grade
    id int auto_increment primary key,
    studentId int not null,
    courseId int not null,
    term int not null, -- term (I am using 100 in below examples for this term)
    attendance int not null, -- whatever you want, 100=always there, 0=he must have been partying,
    grade int not null, -- just an idea   
    -- See (Note Composite Index) at bottom concerning next two lines.
    unique key(studentId,courseId,term), -- no duplicates allowed for the combo (note student can re-take it next term)
    key (courseId,studentId),
    CONSTRAINT fk_sc_student FOREIGN KEY (studentId) REFERENCES student(studentId),
    CONSTRAINT fk_sc_courses FOREIGN KEY (courseId) REFERENCES course(courseId)
);

Testgegevens maken

insert student(fullName) values ('Henry Carthage'),('Kim Billings'),('Shy Guy'); -- id's 1,2,3
insert student(fullName) values ('Shy Guy');

insert dept(deptName) values ('History'),('Math'),('English'); -- id's 1,2,3

insert course(deptId,courseName) values (1,'Early Roman Empire'),(1,'Italian Nation States'); -- id's 1 and 2 (History dept)
insert course(deptId,courseName) values (2,'Calculus 1'),(2,'Linear Algebra A'); -- id's 3 and 4 (Math dept)
insert course(deptId,courseName) values (3,'World of Chaucer'); -- id 5 (English dept)

-- show why FK constraints are important based on data at the moment
insert course(deptId,courseName) values (66,'Fly Fishing 101'); -- will generate error 1452. That dept 66 does not exist
-- That error is a good error to have. Better than faulty data

-- Have Kim (studentId=2) enrolled in a few courses
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,1,100,-1,-1); -- Early Roman Empire, term 100 (made up), unknown attendance/grade
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,4,100,-1,-1); -- Linear Algebra A
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,5,100,-1,-1); -- World of Chaucer

-- Have Shy Guy (studentId=3) enrolled in one course only. He is shy
insert SCJunction(studentId,courseId,term,attendance,grade) values (3,5,100,-1,-1); -- Early Roman Empire, term 100 (made up), unknow attendance/grade
-- note if you run that line again, the Error 1062 Duplicate entry happens. Can't take same course more than once per term

Enkele eenvoudige vragen.

Welke cursus is in welke afdeling?

alles weergeven, gebruikt tabelaliassen (afkortingen) om typen minder, leesbaarheid (soms) beter te maken

select c.courseId,c.courseName,d.deptId,d.deptName
from course c
join dept d
on c.deptId=d.deptId
order by d.deptName,c.courseName -- note the order
+----------+-----------------------+--------+----------+
| courseId | courseName            | deptId | deptName |
+----------+-----------------------+--------+----------+
|        5 | World of Chaucer      |      3 | English  |
|        1 | Early Roman Empire    |      1 | History  |
|        2 | Italian Nation States |      1 | History  |
|        3 | Calculus 1            |      2 | Math     |
|        4 | Linear Algebra A      |      2 | Math     |
+----------+-----------------------+--------+----------+

Wie volgt de cursus World of Chaucer dit semester?

(kennen van de courseId=5)

Het onderstaande profiteert van een van onze samengestelde indexen in SCJunction. Een composiet is een index op meer dan één kolom.

select s.StudentId,s.FullName
from SCJunction j
join student s
on j.studentId=s.studentId
where j.courseId=5 and j.term=100
+-----------+--------------+
| StudentId | FullName     |
+-----------+--------------+
|         2 | Kim Billings |
|         3 | Shy Guy      |
+-----------+--------------+

Kim Billings is ingeschreven voor welke termijn?

select s.StudentId,s.FullName,c.courseId,c.courseName
from SCJunction j
join student s
on j.studentId=s.studentId
join course c
on j.courseId=c.courseId
where s.studentId=2 and j.term=100
order by c.courseId DESC -- descending, just for the fun of it
+-----------+--------------+----------+--------------------+
| StudentId | FullName     | courseId | courseName         |
+-----------+--------------+----------+--------------------+
|         2 | Kim Billings |        5 | World of Chaucer   |
|         2 | Kim Billings |        4 | Linear Algebra A   |
|         2 | Kim Billings |        1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+

Kim is overweldigd, dus drop drop de wiskundeles

delete from SCJunction
where studentId=2 and courseId=4 and term=100

voer dat bovenstaande select-statement uit om te laten zien wat Kim neemt:

+-----------+--------------+----------+--------------------+
| StudentId | FullName     | courseId | courseName         |
+-----------+--------------+----------+--------------------+
|         2 | Kim Billings |        5 | World of Chaucer   |
|         2 | Kim Billings |        1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+

Ah, veel gemakkelijker term. Papa zal echter niet blij zijn.

Let op zaken als SCJunction.term. Daar kan veel over geschreven worden, ik zal het nu vooral overslaan, behalve om te zeggen dat het ook nog ergens in een FK moet staan. Misschien wilt u dat uw term er meer uitziet als SPRING2015 en niet als een int.

En voor zover id's gaan. Dit is de manier waarop ik het zou doen. Het is persoonlijke voorkeur. Het zou vereisen dat u de id #'s kent en ze opzoekt. Anderen kunnen ervoor kiezen om een ​​cursus-ID te hebben, zoiets als HIST101 en niet 17. Die zijn veel beter leesbaar (maar langzamer in de index (nauwelijks). Dus doe wat het beste voor je is.

Opmerking Samengestelde Index

Een samengestelde index (INDEX betekent KEY en vice versa) is een index die meerdere kolommen combineert voor het snel ophalen van gegevens. De orders worden omgedraaid voor de twee samenstellingen in de SCJunction-tabel, zodat, afhankelijk van het universum van query's die achter uw gegevens aan gaan, de db-engine kan kiezen welke index moet worden gebruikt voor het snelst ophalen op basis van de meest linkse kolom waar u achteraan gaat .

Wat betreft de unieke sleutel, #1, de opmerking ernaast waarin staat dat er geen duplicaten worden afgedwongen (wat betekent dat ongewenste gegevens worden gebruikt) spreekt voor zich. Student 1 cursus 1 semester 1 kan bijvoorbeeld niet twee keer voorkomen in die tabel.

Een cruciaal concept om te begrijpen is het concept van left-most volgorde van kolomnamen in een index.

Voor zoekopdrachten die na studentId . gaan alleen , dan de sleutel met studentId als eerste vermeld (left-most ) is gebruikt. In zoekopdrachten die na courseId . komen alleen , dan de sleutel met courseId meest linkse wordt gebruikt. Bij zoekopdrachten die achter zowel studentId als courseId komen, kan de db-engine beslissen welke samengestelde sleutel moet worden gebruikt.

Als ik zeg "ga erna", bedoel ik in de on clause of where clause staat.

Zou men die twee samengestelde sleutels niet hebben (met de kolom 1 en 2 erin omgedraaid), dan in zoekopdrachten waarbij de gezochte kolom niet left-most is geïndexeerd, zou u geen voordeel halen uit het gebruik van sleutels en een langzame tabelscan hebben voor gegevens om terug te keren.

Dus die twee indexen combineren de volgende 2 concepten

  • Snel ophalen van gegevens op basis van meest linkse of beide (kolommen studentId en courseId)
  • Niet-duplicatie van gegevens in die tabel afdwingen op basis van studentId-, courseId- en termwaarden

De afhaalmaaltijd

De belangrijke afhaalmaaltijd is dat Junction-tabellen zorgen voor het snel ophalen van indexen en gezond beheer van gegevens versus door komma's gescheiden gegevens (array-mindset) die in een kolom zijn gepropt, en alle ellende van het gebruik van zo'n constructie.



  1. Een database-e-mailaccount verwijderen in SQL Server (T-SQL)

  2. Is er zoiets als een zip()-functie in PostgreSQL die twee arrays combineert?

  3. Optimalisatiedrempels - Gegevens groeperen en aggregeren, deel 2

  4. Een titel toevoegen aan een formulierkoptekst in Microsoft Access