Mysql
 sql >> база данни >  >> RDS >> Mysql

Как да съхранявате няколко опции в една таблица?

Моля, прочетете за Нормализация на данните , Общо индексиране концепции и Външен ключ ограничения за поддържане на данните чисти с референтна цялост. Това ще ви накара да продължите.

Съхраняването на данни в масиви може да ви изглежда естествено на хартия, но за db машината производителността е предимно без използване на индекс. Освен това на Ден 2 ще откриете, че достигането и поддържането на вашите данни ще бъде кошмар.

Следното трябва да ви даде добър старт, докато бърникате. Присъединява също.

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)
);

Създаване на тестови данни

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

Някои прости въпроси.

Какъв курс е в кой отдел?

показване на всички, използва псевдоними на таблици (съкращения), за да направи писането по-малко, четливостта (понякога) по-добра

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     |
+----------+-----------------------+--------+----------+

Кой изучава курса по света на Чосър този термин?

(знайки курса Id=5)

По-долу се възползва от един от нашите съставни индекси в SCJunction. Композитът е индекс на повече от една колона.

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      |
+-----------+--------------+

Ким Билингс е записана в какво е този термин?

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 |
+-----------+--------------+----------+--------------------+

Ким е претоварена, така че зарежете часа по математика

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

стартирайте това по-горе изявление за избор, показващо какво приема Ким:

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

А, много по-лесен термин. Татко обаче няма да е доволен.

Обърнете внимание на такива неща като SCJunction.term. Много може да се напише за това, в момента ще го пропусна най-вече, освен да кажа, че трябва да е и във FK някъде. Може да искате терминът ви да изглежда по-скоро като ПРОЛЕТ 2015, а не като цяло.

И що се отнася до id. Това е начинът, по който бих го направил. Това е лично предпочитание. Ще е необходимо да знаете идентификационните номера и да ги търсите. Други биха могли да изберат да имат идентификатор на курса нещо като HIST101, а не 17. Те са много по-четливи (но по-бавни в индекса (едва). Така че правете това, което е най-добро за вас.

Сложен индекс на бележка

Съставният индекс (ИНДЕКС означава КЛЮЧ и обратно) е този, който комбинира множество колони за бързо извличане на данни. Поръчките се обръщат за двата композита в таблицата SCJunction, така че в зависимост от вселената от заявки, които вървят след вашите данни, db машината може да избере кой индекс да използва за най-бързо извличане въз основа на най-лявата колона, която търсите .

Що се отнася до уникалния ключ, #1, коментарът до него, в който се посочва, че не се прилагат дубликати (което означава нежелани данни), е по-скоро разбираем. Например студент 1 курс 1 семестър 1 не може да съществува два пъти в тази таблица.

Решаваща концепция за разбиране е концепцията за left-most подреждане на имената на колони в индекс.

За заявки, които вървят след studentId само , след това ключа, който има studentId изброени първи (left-most ) се използва. В заявки, които вървят след courseId само , след това ключа, който има courseId използва се най-ляво. При заявки, които вървят след studentId и courseId, db машината може да реши кой съставен ключ да използва.

Когато казвам „върви след“, имам предвид в клаузата on clause или where clause състояние.

Ако някой нямаше тези два съставни ключа (с обърнати колони 1 и 2 в тях), тогава при заявки, където търсената колона не е left-most Индексирани, няма да имате полза от използването на ключове и ще претърпите бавно сканиране на таблици за връщане на данни.

И така, тези два индекса комбинират следните 2 понятия

  • Бързо извличане на данни въз основа на най-ляво или и двете (колони studentId и courseId)
  • Налагане на недублиране на данни в тази таблица въз основа на studentId, courseId и стойности на термина

Вземането за вкъщи

Важното за вставане е, че таблиците на Junction осигуряват бързо извличане на индекси и разумно управление на данни срещу данни, разделени със запетая (нагласа на масива), натъпкани в колона, и цялата мизерия от използването на такава конструкция.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Моите MySQL сървърни връзки криптирани и безопасни ли са?

  2. Свързване с MySQL база данни в .NET

  3. SQLite INSERT - ПРИ АКТУАЛИЗИРАНЕ НА ДУБЛИКАТ КЛЮЧ (UPSERT)

  4. Използване на клауза union и order by в mysql

  5. Как да увелича MySQL връзките(max_connections)?