Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm thế nào để lưu trữ nhiều tùy chọn trong một bảng?

Vui lòng đọc thêm về Chuẩn hóa dữ liệu , Lập chỉ mục chung khái niệm và Khóa ngoại các ràng buộc để giữ cho dữ liệu sạch sẽ với tính toàn vẹn tham chiếu. Điều này sẽ giúp bạn tiến lên.

Lưu trữ dữ liệu trong mảng có vẻ tự nhiên đối với bạn trên giấy, nhưng đối với công cụ db, hiệu suất chủ yếu là không sử dụng chỉ mục. Hơn nữa, bạn sẽ thấy vào Ngày thứ 2 rằng việc truy cập và duy trì dữ liệu của bạn sẽ là một cơn ác mộng.

Những điều sau đây sẽ giúp bạn có một khởi đầu tốt khi bạn mày mò. Tham gia quá.

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

Tạo dữ liệu thử nghiệm

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

Một số câu hỏi đơn giản.

Khóa học ở khoa nào?

hiển thị tất cả, sử dụng bí danh bảng (chữ viết tắt) để làm cho việc nhập ít hơn, khả năng đọc (đôi khi) tốt hơn

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

Ai sẽ tham gia khóa học World of Chaucer trong học kỳ này?

(biết khóa họcId =5)

Những lợi ích dưới đây từ một trong các chỉ mục tổng hợp của chúng tôi trong SCJunction. Tổng hợp là một chỉ mục trên nhiều cột.

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 đã đăng ký học gì trong học kỳ này?

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 bị choáng ngợp nên bỏ học môn toán

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

chạy câu lệnh select phía trên hiển thị những gì Kim đang dùng:

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

Ah, thuật ngữ dễ dàng hơn nhiều. Bố sẽ không vui đâu.

Lưu ý những điều như SCJunction.term. Có thể viết nhiều về điều đó, tôi sẽ bỏ qua phần lớn vào lúc này, ngoài việc nói rằng nó cũng nên có trong một FK ở đâu đó. Bạn có thể muốn thuật ngữ của mình trông giống với SPRING2015 hơn chứ không phải là số nguyên.

Và theo như id đã đi. Đây là cách tôi sẽ làm. Đó là sở thích cá nhân. Nó sẽ yêu cầu biết id #, tìm kiếm chúng. Những người khác có thể chọn có một khóa học giống như HIST101 chứ không phải 17. Khóa học này dễ đọc hơn (nhưng chỉ mục chậm hơn (hầu như không). Vì vậy, hãy làm những gì tốt nhất cho bạn.

Chỉ mục tổng hợp ghi chú

Chỉ mục tổng hợp (INDEX có nghĩa là KEY và ngược lại) là chỉ mục kết hợp nhiều cột để truy xuất dữ liệu nhanh chóng. Các đơn đặt hàng được lật cho hai vật liệu tổng hợp trong bảng SCJunction, do đó, tùy thuộc vào vô số truy vấn theo sau dữ liệu của bạn, công cụ db có thể chọn chỉ mục nào sẽ sử dụng để truy xuất nhanh nhất dựa trên cột ngoài cùng bên trái mà bạn đang truy cập. .

Đối với khóa duy nhất, # 1, nhận xét bên cạnh nó nói rằng thực thi không có bản sao (có nghĩa là dữ liệu rác) khá dễ hiểu. Ví dụ:sinh viên 1 khóa 1 học kỳ 1 không thể tồn tại hai lần trong bảng đó.

Một khái niệm quan trọng cần hiểu là khái niệm left-most thứ tự của tên cột trong một chỉ mục.

Đối với các truy vấn đi sau studentId chỉ , sau đó là khóa có studentId được liệt kê đầu tiên (left-most ) Được sử dụng. Trong các truy vấn sau courseId chỉ , sau đó là khóa có courseId phần lớn bên trái được sử dụng. Trong các truy vấn đặt sau cả studentId và courseId, công cụ db có thể quyết định sử dụng khóa tổng hợp nào.

Khi tôi nói "đi sau", ý tôi là trong mệnh đề on clause hoặc where clause điều kiện.

Nếu không có hai khóa tổng hợp đó (với cột 1 và 2 trong đó được lật), thì trong các truy vấn mà cột được tìm kiếm không phải là left-most được lập chỉ mục, bạn sẽ không được lợi với việc sử dụng khóa và phải chịu một quá trình quét bảng chậm để dữ liệu trả về.

Vì vậy, hai chỉ số đó kết hợp 2 khái niệm sau đây

  • Truy xuất dữ liệu nhanh chóng dựa trên phần ngoài cùng bên trái hoặc cả hai (cột studentId và courseId)
  • Thực thi không trùng lặp dữ liệu trong bảng đó dựa trên các giá trị studentId, courseId và term

Takeaway

Điều quan trọng là bảng Junction giúp truy xuất chỉ mục nhanh chóng và quản lý dữ liệu lành mạnh so với dữ liệu được phân tách bằng dấu phẩy (tư duy mảng) được nhồi nhét vào một cột và tất cả những điều khốn khổ khi sử dụng một cấu trúc như vậy.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để đếm từ trong MySQL / thay thế biểu thức chính quy?

  2. Danh sách các chỉ định định dạng ngày trong MySQL

  3. mã php để kiểm tra pdo có sẵn không?

  4. Cơ sở dữ liệu MySQL có thể lớn đến mức nào trước khi hiệu suất bắt đầu giảm

  5. Kết nối các ứng dụng ODBC với MySQL