Nel*_*oza 9 mysql database-design
我想设计一个结果计算应用程序.
首先,我需要知道如何在MySQL数据库中存储记录,以便学生可以连接多个课程,例如学生A可以有6个科目,而学生B可以有12个科目附加给他.
在这种情况下,我需要知道如何设计一个数据库结构,允许字段以数组的形式存储尽可能多的主题.
任何建议或更好的方法来处理这一点将非常感激.
Dre*_*rew 30
请阅读数据规范化,常规索引概念和外键约束,以使参照完整性保持数据清洁.这会让你前进.
在数组中存储数据对您来说似乎很自然,但对于数据库引擎而言,性能主要是没有索引使用.此外,您将在第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)
);
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
一些简单的问题.
show all,使用表别名(缩写)使输入更少,可读性(有时)更好
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 |
+----------+-----------------------+--------+----------+
Run Code Online (Sandbox Code Playgroud)
(知道courseId = 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 |
+-----------+--------------+
Run Code Online (Sandbox Code Playgroud)
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 |
+-----------+--------------+----------+--------------------+
Run Code Online (Sandbox Code Playgroud)
Kim不知所措,所以放弃了数学课
delete from SCJunction
where studentId=2 and courseId=4 and term=100
Run Code Online (Sandbox Code Playgroud)
运行上面的选择语句,显示Kim正在采取的措施:
+-----------+--------------+----------+--------------------+
| StudentId | FullName | courseId | courseName |
+-----------+--------------+----------+--------------------+
| 2 | Kim Billings | 5 | World of Chaucer |
| 2 | Kim Billings | 1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+
Run Code Online (Sandbox Code Playgroud)
啊,这个术语容易得多.爸爸不会高兴.
注意SCJunction.term之类的东西.关于这个问题可以写得很多,我现在大部分会跳过它,而不是说它应该在某个地方的FK中.您可能希望您的术语看起来更像SPRING2015而不是int.
而且就id而言.这就是我这样做的方式.这是个人喜好.这需要知道id#,查找它们.其他人可以选择一个类似HIST101而不是17的课程.这些更具可读性(但在索引中速度较慢(几乎没有).那么做什么最适合你.
复合索引(INDEX表示KEY,反之亦然)是组合多列以进行快速数据检索的索引.SCJunction表中的两个合成项的顺序将被翻转,这样,根据您的数据之后的查询范围,数据库引擎可以根据您要追踪的最左侧列选择要用于最快检索的索引. .
至于唯一键#1,它旁边的注释声明强制执行没有重复(意味着垃圾数据)是相当不言自明的.例如,学生1课程1学期1在该表中不能存在两次.
要理解的关键概念是left-most索引中列名的排序概念.
对于studentId 仅后跟的查询,则使用studentId列出first(left-most)的键.在courseId 仅后续查询中,courseId使用最左侧的键.在追踪studentId和courseId的查询中,db引擎可以决定使用哪个复合键.
当我说"追求"时,我的意思是在on clause或者where clause条件.
如果没有这两个复合键(其中第1列和第2列被翻转),那么在查询列未被left-most索引的查询中,您将无法获得密钥使用,并且数据返回时会遇到缓慢的表扫描.
因此,这两个索引结合了以下两个概念
重要的外卖是,结表作出快速索引检索和数据与塞进一列逗号分隔的数据(数组心态)的健全的管理,和使用这样的构建体的所有的痛苦.
| 归档时间: |
|
| 查看次数: |
5580 次 |
| 最近记录: |