|
假定希望看到1 9 9 9年9月2 3号的学分,针对某个特定日期中给出的事件的学分查询如下所示:
 相当吓人,是吗?这个查询通过将score 表的记录与event 表的记录连接(关联)来检索学生名、日期、学分和学分的类型。其结果如下所示:
 您肯定注意到了,它与图1-4 中给出的表设计相同,而且不需要知道事件ID 就可得出这个结果,只需指出感兴趣的日期并让MySQL 查找出哪个学分记录具有该日期即可。如果您一直担心抽象和分解会使我们损失一些东西的话,看到这个世界,就不会有这种担心了。 当然,在考虑过查询后,您还可能对其他别的东西产生担心。即,这个查询看上去有点长并且也有点复杂;是不是做了很多工作写出这样的东西只是为了查找某个给定日期的学分?是的,确实是这样。但是,在每次想要发布一个查询时,有几种方法可以避免键入多行的S Q L。一般情况下,一旦您决定如何执行这样一个查询并将它保存起来后,就可以按需要多次执行它。我们将在1 . 5节“与mysql 交互的技巧”中介绍怎样完成这项工作。 在上述查询的介绍中,我们有点超前了。不过,这个查询比起我们要实际用来得出学分的查询是有点简单了。原因是,我们还要对表的设计作更多的修改。我们将采用一个唯一的学生I D,而不在score 表中记录学生名。(即,我们将使用来自学分簿的“ I D”列的值而不是来自“ N a m e”列的值。)然后,创建另一个称为student 的表来存放name 和student_id 列(见图1 - 7)。
 为什么要作出这种修改呢?只有一个原因,可能有两个学生有相同的名字。采用唯一的学生ID 号可帮助区分他们的学分。(这与利用唯一的事件ID 而不是日期来分辨出相同日期的测试或测验完全类似。)在对表的设计作了这样的修改后,实际用来获得给定日期的学分查询变得更为复杂了一些,这个查询如下:
 如果您不能立即清楚地读懂这个查询的意思的话,也不必担心。在进一步深入这个教程之后,就能看懂这个查询了。将会从图1 - 7中注意到,在student 表中增加了点学分簿中没有的东西。它包含了一个性别列。这便可以做一些简单的事情,如对班级中男孩和女孩的人数计数;也可以做一些更为复杂的事情,如比较男孩和女孩的学分。我们已经设计完了学分保存的几乎所有的表。现在只需要另外 一个表来记录出勤情况即可。这个表的内容相对较为直观,即,一个学生ID 号和一个日期(见图1 - 8)。表中的每行表示特定的学生在 给定的日期缺勤。在学分时段末,我们将调用MySQL 的计数功能来汇总此表的内容,以便得出每个学生的缺勤数。
 既然现在已经知道学分保存的各个表的结构,现在可以创建它们了。student 表的C R E ATE TABLE 语句如下:
 将上述语句键入mysql 或执行下列外壳程序命令:
 C R E ATE TABLE 语句创建了一个名为student 的表,它含有三列,分别为: n a m e、s e x和s t u d e n t _ i d。name 是一个可变长的字符串列,最多可存放20 个字符。这个名字的表示比历史同盟表中所用的表示要简单,它只用了单一的列而不是分别的名和姓列。这是因为我们已经预先知道,不存在无需做另外的工作就使得在多个列上工作得更好的查询样例。sex 表示学生是男孩还是女孩。这是一个E N U M(枚举)列,表示只能取明确地列在说明中的值之一,这里列出的值为:“F”和“M”,分别表示女和男。在某列只具有一组有限值时,ENUM 类型非常有用。我们可以用CHAR(1) 来代替它,但是ENUM 更明确规定了列可以取什么值。如果对包括一个ENUM 列的表发布一条DESCRIBE tbl_name 语句,MySQL 将确切地显示可取的值有哪些。顺便说一下, ENUM 列中的值不一定只是单个字符。此列还可以定义为E N U M(‘f e m a l e’,‘m a l e’)。 student_id 为一个整数型列,它将包含唯一的ID 号。通常,大概会从一个中心资料来源处(如学校办公室)取得学生的ID 号,但在这里是我们自己定的。虽然student_id 列只包含一个数,但其定义包括几个部分: ■ INT 说明此列的值必须取整数(即无小数部分)。 ■ UNSIGNED 不允许负数。 ■ NOT NULL 表示此列的值必须填入。(任何学生都必须有一个ID 号。) ■ A U TO_INCREMENT 是MySQL 中的一个特殊的属性。其作用为:如果在创建一个新的student 表记录时遗漏了student_id 的值(或为N U L L),MySQL 自动地生成一个大于当前此列中最大值的唯一ID 号。在录入学生表时将用到这个这特性,录入学生表时可以只给出name 和sex 的值,让MySQL 自动生成student_id 列值。 ■ P R I M A RY KEY 表示相应列的值为快速查找进行索引,并且列中的每个值都必须是惟一的。这样可防止同一名字的I D出现两次,这对于学生ID 号来说是一个必须的特性。(不仅如此,而且MySQL 还要求每个A U TO_INCREMENT 列都具有一个惟一索引。)如果您不理解A U TO_INCREMENT 和P R I M A RY KEY 的含义,只要将其想像为一种为每个学生产生ID 号的魔术方法即可。除了要求值唯一外,没有什么别的东西。请注意:如果确实打算从学校办公室取得学生ID 号而不是自动生成它们,则可以按相同的方法定义student_id 列,只不过不定义A U TO_INCREMENT 属性即可。event 表如下定义:
 将此语句键入mysql 或执行下列外壳程序的命令:
 所有列都定义为NOT NULL,因为它们中任何一个值都不能省略。date 列存储标准的MySQL DATE 日期值,格式为“Y Y Y Y- M M - D D”(首先是年)。type 代表学分类型。像student 表中的sex 一样,type 也是一个枚举列。所允许的值为“T”和“Q”,分别表示“测试”和“测验”。event_id 是一个AUTO_INCREMENT 列,类似于student 表中的student_id 列。采用AUTO_INCREMENT 允许生成唯一的事件ID 值。正如student 表中的student_id 列一样,与值的惟一性相比,某个特定的值并不重要。score 表如下定义:
 将此语句键入mysql 或执行下列外壳程序的命令:
 score 为一个INT (整型)列。即,假定学分值总是为一个整数。如果希望使学分值具有小数部分,如5 8 . 5,应该采用浮点列类型,如F L O AT 或D E C I M A L。student_id 列和event_id 列都是整型,分别表示每个学分所对应的学生和事件。通过利用它们来连接到student 和event 表,我们能够知道学生名和事件的日期。我们将两个列组成了P R I M A RY KEY。这保证我们不会对同一测验或测试重复一个学生的学分。而且,这样还很容易在以后更改某个学分。例如,在发现学分录入错时,可以在利用MySQL 的R E P L A C E语句放入一个新记录,替换掉旧的记录。不需要执行DELETE 语句与I N S E RT 语句;M y S Q L自动替我们做了。请注意,它是惟一的event_id 和student_id 的组合。在score 表中,两者自身都可能不惟一。一个event_id 值可有多个学分记录(每个学生对应一个记录),而每个student_id 值都对应多个记录(每个测验和测试有一个记录)。用于出勤情况的absence 表如下定义:
 将此语句键入mysql 或执行下列外壳程序的命令:
 student_id 和date 列两者都定义为NOT NULL,不允许省略值。应定义这两列的组合为主键,以免不当心建立了重复的记录。重要的是不要对同一天某个学生的缺旷进行重复计数。
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ... 下一页 >> |