转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 数据库 >> MySql >> 正文
MySQL教程(4)         ★★★★

MySQL教程(4)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:674 更新时间:2009/4/22 20:43:30
    但是,以这种方式设置表似乎有点问题。好像少了点什么。请看图1- 3中的记录,我们分辨不出是测验的学分还是测试的学分。如果测验和测试的学分权重不同,在确定最终的学分等级时知道学分的类型是很重要的。或许可以试着从学分的取值范围来确定学分的类型(测验的学分一般比测试的学分少),但是这样做很不方便,因为这需要进行判断,而且在数据中也不明显。可以通过记录学分的类型来进行区分,如对学分表增加一列,此列包含“ T”或“Q”以表示是“测试”或是“测验”,如图1-4 所示。这具有使学分数据类型清析易辨的优点。不利的地方是这个信息有点冗余。显然对具有同一给定日期的记录,学分的类型列总是取相同的值。9月2 3日的学分总是为“ Q”类型,而10月1日的学分其类型总是具有“ T”类型。这样令人很不满意。如果我们以这种方式记录一组测验或测试的学分,不仅要为每个新记录输入相同的日期,而且还要一再重复地输入相同的学分类型。谁会希望一再输入冗余的信息呢?

    我们可以试试另外一种表示。不在score 表中记录学分类型,而是从日期上区分它们。我们可以做一个日期列表,用它来记录每个日期发生的“学分事件”(测验或测试)。然后可以将学分与这个事件列表中的信息结合,确定学分是测验学分还是测试学分。这只要将score 表记录中的日期与event 表中的日期相匹配得出事件类型即可。图1- 5示出这个表的设计并演示了score 表记录与9月2 3日这个日期相关联的工作。通过将score 表中的记录与event 表中记录相对应,我们知道这个学分来自测验。

    这比根据某些猜测来推断学分类型要好得多;我们可以根据明确记录在数据库中的数据来直接得到学分类型。这也比在score 表中记录学分类型更好,因为我们只需对每个类型记录一次。
    但是,在第一次听到这种事情时(即结合使用多个表中的信息),可能会想,“嗯,这是一个好主意,但是不是要做很多工作呢?会不会使工作更复杂了?”在某种程度上,这种想法是对的。处理两个记录表比处理一个要复杂。但是再来考察一下学分簿(见图1- 2)。不是也记录了两套东西吗?考虑下列事实:
    ■ 在学分矩阵中用两个单元记录学分,其中每个单元都是按学生名字和日期(在矩阵的旁边和顶上)进行索引的。这代表了一组记录;与score 表的作用相同。
    ■ 怎样知道每个日期代表的事件类型呢?在日期上方写了字符“ T”或“Q”!因此,也在矩阵顶上记录了日期和学分类型之间的关系。它代表第二组记录;与event 表的作用相同。
    换句话说,这里建议在两个表中记录信息与用学分簿记录信息所做的工作没什么不同。唯一不同的是,这两组信息在学分簿中不是那么明显地被分开。在图1- 5中所示的event 表的设计中加了一个要求,那就是日期必须是唯一的,因为要用它连接score 与event 表的记录。换句话说,同一天不能进行两次测验,或者同一天不能进行一次测验和一次测试。否则,将会在score 表中有两个记录并且在event 表中也有两个记录,全都具有相同的日期,这时就不知道应如何将score 的记录与event 的记录进行匹配。如果每天不多于一个学分事件,这就是一个永远不会出现的问题,可是事实并非如此简单。有时,一天中可能会有不止一个学分事件。我常听有的人说他们的数据,“那种古怪情况从不会出现。”然而,如果这种情况确实出现时,就必须重新设计表以适应这种情况引起的问题。最好是预先考虑以后可能出现的问题,并预先准备好怎样处理他们。因此,我们假定有时可能会需要同一天记录两组学分。我们怎样处理呢?如果出现这种情况,问题并不难解决。只要对处理数据的方式作一点小的更改,就可使同一日期上有多个事件而不会引起问题:
    1) 增加一个列到event 表,并用它来给表中每个记录分配一个唯一的编号。实际上这就给了每个事件一个唯一的ID 号,因此我们称该列为event_id 列。(如果觉得这好像是做傻事,可看一下图1-2 中的学分簿,其中已经有这个特征了。事件ID 正好与学分簿分数矩阵中列号相似。这个编号可能没有清晰地写在那儿并标上“事件ID,”但是它确实在那儿。)
   2) 当向score 表中输入学分时,输入的是事件ID 而不是日期。这些改变的结果如图1-6 所示。现在连接score 和event 表时,用的是事件ID 而不是日期,而且不仅用event 表来决定每个学分的类型,而且还用它来决定其日期。并且在event 表中不再有日期必须唯一这个限制,而唯一的是事件ID。这表示同一天可以有一打测试和测验,而且能够在记录里边直接保存它们。(毫无疑问,学生们听到这个一定浑身发抖。)不幸的是,从人的观点来看,图1-6 中的表设计较前一个更不能令人满意。score 表也更为抽象一些,因为它包含的从直观上可以理解的列更少。而图1-4 中此表的设计直观且容易理解,因为那个score 表具有日期和学分类型的列。当前的score 表如图1-6 所示,日期和学分类型的列都没有了。这极大地去除了作为人能够很容易考虑的一切。谁希望看到其中有“事件ID”的score 表?如果有的话,也不代表我们大多数人。

    此时,可看到能够电子化地完成学分记录,且在赋予学分等级时不必做各种乏味的手工计算。但是,在考虑了如何实际在一个数据库中表示学分信息后,又会被怎样抽象和拆分组成学分信息的表示难住了。自然会产生一个问题:“根本不使用数据库可能会更好一些?或许MySQL不适合我?”正如您所猜测的那样,笔者将从否定的方面对这个问题进行回答,否则这本书就没必要再往下写了。不过,在考虑如何做一件工作时,应考虑各种情况并提问是否最好不使用数据库系统(如MySQL)而使用一些别的东西(如电子表格等):
    ■ 学分簿有行和列,而电子表格也有。这使学分簿和电子表格在概念上和外观上都非常类似。
    ■ 电子表格能够完成计算,可以利用一个计算字段来累计每个学生的学分。但是,要对测验和测试进行加权可能有点麻烦,但这也是可以办得到的。另一方面,如果希望只查看某部分数据(如只查看学分或测试),进行诸如男孩与女孩的比较,或以一种灵活的方式显示合计信息等,情况又大有不同了。电子表格的功能显得要差一些,而关系数据库系统完成这些工作相当容易。另外要考虑的一点是为了在关系数据库中进行表示而对数据进行抽象和分解,这个问题并不真的那么难以应付。只要考虑安排数据库使其不会以一种对您希望做的事无意义的方式来表示数据即可。但是,在确定了表示方式之后,就要靠数据库引擎来协调和表示数据了。您肯定不会希望将它视为一堆支离破碎的东西。
    例如,在从score 表中检索学分时,不希望看到事件ID;但希望看到日期。这没有什么问题。数据库将会根据事件ID 从event 表中查找出日期。您还可能想要看看是测验的学分或测试的学分。这也不成问题。数据库将用相同的方法查找出学分类型,也是利用事件ID。请记住,这就是如像MySQL这样的关系数据库的优势所在,即,使一样东西与另一样东西相关联,以便从多个来源得出信息并以您实际想看到的形式提供出来。在学分保存数据的情况中,MySQL确实利用事件ID 将信息组合到了一起,而无需人工来完成这件事。
现在我们先来看看,如何使MySQL完成这种将一个东西与另一个东西相联系的工作。
    假定希望看到1999年9月2 3号的学分,针对某个特定日期中给出的事件的学分查询如下所示:

    相当吓人,是吗?这个查询通过将score 表的记录与event 表的记录连接(关联)来检索学生名、日期、学分和学分的类型。其结果如下所示:

    您肯定注意到了,它与图1-4 中给出的表设计相同,而且不需要知道事件ID 就可得出这个结果,只需指出感兴趣的日期并让MySQL查找出哪个学分记录具有该日期即可。如果您一直担心抽象和分解会使我们损失一些东西的话,看到这个世界,就不会有这种担心了。
当然,在考虑过查询后,您还可能对其他别的东西产生担心。即,这个查询看上去有点长并且也有点复杂;是不是做了很多工作写出这样的东西只是为了查找某个给定日期的学分?是的,确实是这样。但是,在每次想要发布一个查询时,有几种方法可以避免键入多行的SQL。一般情况下,一旦您决定如何执行这样一个查询并将它保存起来后,就可以按需要多次执行它。我们将在1. 5节“与mysql交互的技巧”中介绍怎样完成这项工作。
    在上述查询的介绍中,我们有点超前了。不过,这个查询比起我们要实际用来得出学分的查询是有点简单了。原因是,我们还要对表的设计作更多的修改。我们将采用一个唯一的学生ID,而不在score 表中记录学生名。(即,我们将使用来自学分簿的“ ID”列的值而不是来自“ Name”列的值。)然后,创建另一个称为student 的表来存放name 和student_id 列(见图1- 7)。

    为什么要作出这种修改呢?只有一个原因,可能有两个学生有相同的名字。采用唯一的学生ID 号可帮助区分他们的学分。(这与利用唯一的事件ID 而不是日期来分辨出相同日期的测试或测验完全类似。)在对表的设计作了这样的修改后,实际用来获得给定日期的学分查询变得更为复杂了一些,这个查询如下:

    如果您不能立即清楚地读懂这个查询的意思的话,也不必担心。在进一步深入这个教程之后,就能看懂这个查询了。将会从图1- 7中注意到,在student 表中增加了点学分簿中没有的东西。它包含了一个性别列。这便可以做一些简单的事情,如对班级中男孩和女孩的人数计数;也可以做一些更为复杂的事情,如比较男孩和女孩的学分。我们已经设计完了学分保存的几乎所有的表。现在只需要另外
一个表来记录出勤情况即可。这个表的内容相对较为直观,即,一个学生ID 号和一个日期(见图1- 8)。表中的每行表示特定的学生在
给定的日期缺勤。在学分时段末,我们将调用MySQL的计数功能来汇总此表的内容,以便得出每个学生的缺勤数。

    既然现在已经知道学分保存的各个表的结构,现在可以创建它们了。student 表的CREATE TABLE 语句如下:

    将上述语句键入mysql或执行下列外壳程序命令:

   CREATE TABLE 语句创建了一个名为student 的表,它含有三列,分别为: name、s e x和s t ud e n t _ i d。name 是一个可变长的字符串列,最多可存放20 个字符。这个名字的表示比历史同盟表中所用的表示要简单,它只用了单一的列而不是分别的名和姓列。这是因为我们已经预先知道,不存在无需做另外的工作就使得在多个列上工作得更好的查询样例。sex 表示学生是男孩还是女孩。这是一个ENUM(枚举)列,表示只能取明确地列在说明中的值之一,这里列出的值为:“F”和“M”,分别表示女和男。在某列只具有一组有限值时,ENUM 类型非常有用。我们可以用CHAR(1) 来代替它,但是ENUM 更明确规定了列可以取什么值。如果对包括一个ENUM 列的表发布一条DESCRIBE tbl_name 语句,MySQL将确切地显示可取的值有哪些。顺便说一下, ENUM 列中的值不一定只是单个字符。此列还可以定义为ENUM(‘f e m a l e’,‘m a l e’)。
    student_id 为一个整数型列,它将包含唯一的ID 号。通常,大概会从一个中心资料来源处(如学校办公室)取得学生的ID 号,但在这里是我们自己定的。虽然student_id 列只包含一个数,但其定义包括几个部分:
    ■ INT 说明此列的值必须取整数(即无小数部分)。
    ■ UNSIGNED 不允许负数。
    ■ NOT NULL 表示此列的值必须填入。(任何学生都必须有一个ID 号。)
    ■ AUTO_INCREMENT 是MySQL中的一个特殊的属性。其作用为:如果在创建一个新的student 表记录时遗漏了student_id 的值(或为NULL),MySQL自动地生成一个大于当前此列中最大值的唯一ID 号。在录入学生表时将用到这个这特性,录入学生表时可以只给出name 和sex 的值,让MySQL自动生成student_id 列值。
    ■ PRIMARY KEY 表示相应列的值为快速查找进行索引,并且列中的每个值都必须是惟一的。这样可防止同一名字的ID出现两次,这对于学生ID 号来说是一个必须的特性。(不仅如此,而且MySQL还要求每个AUTO_INCREMENT 列都具有一个惟一索引。)如果您不理解AUTO_INCREMENT 和PRIMARY KEY 的含义,只要将其想像为一种为每个学生产生ID 号的魔术方法即可。除了要求值唯一外,没有什么别的东西。请注意:如果确实打算从学校办公室取得学生ID 号而不是自动生成它们,则可以按相同的方法定义student_id 列,只不过不定义AUTO_INCREMENT 属性即可。event 表如下定义:

  将此语句键入mysql或执行下列外壳程序的命令:

    所有列都定义为NOT NULL,因为它们中任何一个值都不能省略。date 列存储标准的MySQLDATE 日期值,格式为“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,应该采用浮点列类型,如FLOAT或DECIMAL。student_id 列和event_id 列都是整型,分别表示每个学分所对应的学生和事件。通过利用它们来连接到student 和event 表,我们能够知道学生名和事件的日期。我们将两个列组成了PRIMARY KEY。这保证我们不会对同一测验或测试重复一个学生的学分。而且,这样还很容易在以后更改某个学分。例如,在发现学分录入错时,可以在利用MySQL的REPLACE语句放入一个新记录,替换掉旧的记录。不需要执行DELETE 语句与INSERT 语句;MySQL自动替我们做了。请注意,它是惟一的event_id 和student_id 的组合。在score 表中,两者自身都可能不惟一。一个event_id 值可有多个学分记录(每个学生对应一个记录),而每个student_id 值都对应多个记录(每个测验和测试有一个记录)。用于出勤情况的absence 表如下定义:

    将此语句键入mysql或执行下列外壳程序的命令:

    student_id 和date 列两者都定义为NOT NULL,不允许省略值。应定义这两列的组合为主键,以免不当心建立了重复的记录。重要的是不要对同一天某个学生的缺旷进行重复计数。
    1.4.7 增加新记录


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Sql Server  · MySql
    · Access  · ORACLE
    · SyBase  · 其他
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台