第一章 MYSQL入门与出入
本章要点:
v MySQL标准简介
v 关系数据库系统的知识
v MySQL的优点
v MySQL的SQL语言
MySQL 是完全网络化的跨平台关系型数据库系统,同时是具有客户机/服务器体系结构的分布式数据库管理系统。MySQL在UNIX等操作系统上是免费的,在Windows操作系统上,可免费使用其客户机程序和客户机程序库。
MySQL是一个精巧的SQL数据库管理系统,虽然它不是开放源代码的产品,但在某些情况下你可以自由使用。由于它的功能强大、使用简便、管理方便、运行速度快、安全可靠性强、灵活性、丰富的应用编程接口(API)以及精巧的系统结构,受到了广大自由软件爱好者甚至是商业软件用户的青睐,特别是与Apache和PHP/PERL结合,为建立基于数据库的动态网站提供了强大动力。
1.1 MySQL简介
MySQL的进展是非常快了,越来越多的领域里都可以见到MySQL的身影,在学习如何使用这个强大的系统之前,我们首先要了解MySQL的历史、功能、特点,你会对学习MySQL更具信心。
在正式开始之前,我们现了解一下它的读音。MySQL的官方发音是“My Ess Que Ell”(不是 MY-SEQUEL )。
1.1.1 MySQL是什么?
MySQL是一个真正的多用户、多线程SQL数据库服务器。SQL(结构化查询语言)是世界上最流行的和标准化的数据库语言。MySQL是以一个客户机/服务器结构的实现,它由一个服务器守护程序mysqld和很多不同的客户程序和库组成。
SQL是一种标准化的语言,它使得存储、更新和存取信息更容易。例如,你能用SQL语言为一个网站检索产品信息及存储顾客信息,同时MySQL也足够快和灵活以允许你存储记录文件和图像。
MySQL 主要目标是快速、健壮和易用。最初是因为我们需要这样一个SQL服务器,它能处理与任何可不昂贵硬件平台上提供数据库的厂家在一个数量级上的大型数据库,但速度更快,MySQL就开发出来。自1996年以来,我们一直都在使用MySQL,其环境有超过 40 个数据库,包含 10,000个表,其中500多个表超过7百万行,这大约有100 个吉字节(GB)的关键应用数据。
MySQL建立的基础是业已用在高要求的生产环境多年的一套实用例程。尽管MySQL仍在开发中,但它已经提供一个丰富和极其有用的功能集。
MySQL 最早起始于 1979 年,开始是 Michael “Monty” Widenius 为瑞典的 TcX 公司创建的 UNIREG 数据库工具。1994 年,TcX 开始寻找一个用来开发 Web 应用程序的 SQL 服务器。他们测试了一些商业服务器,但是发现所有服务器对于 TcX 的大型表来说都太慢。他们也试了 mSQL,但它缺乏 TcX 需要的某些功能。因此,Monty 开始开发一种新的服务器。其编程接口明确地设计为类似 mSQL 的编程接口,因为 mSQL 可得到几个免费的工具,所以利用与 mSQL 类似的接口,可以将这些相同的工具用于MySQL 从而大大减少了开发接口的工作。
1995 年,Detron HB公司的 David Axmark 努力争取 TcX公司在因特网上发布 MySQL。David 还做了文档资料方面的工作和使 MySQL 与 GNU 的配置实用程序一起建造的工作。MySQL 3.11.1 在 1996 年以用于 Linux 和 Solaris 系统的二进制分发形式发布。今天,MySQL 正工作在许多平台上,并且二进制和源代码的形式都可以得到。
MySQL 并不是一个开放源代码的产品,因为在某些条件下使用它需要许可证。但是,MySQL 很愿意在开放源代码的团体内得以普及,因为“认证”这个术语并不是非常有约束力的(除非通过出售 MySQL 或出售需要它的服务来挣钱,否则,大体上说 MySQL 一般是免费的)。
MySQL 的普及并不限于开放源代码团体内。虽然它在个人计算机上运行(确实,MySQL 的开发一般在不昂贵的 Linux 系统上进行),但它是可移植的,并且运行在商用操作系统(如 Solaris、Irix 和 Windows)和一直到企业服务器的各种硬件上。此外,它的性能也足以和任何其他系统相匹敌,而且它还可以处理具有数百万个记录的大型数据库。
MySQL 的广泛应用前景在我们面前尚未完全展开,如运行在功能强但不昂贵的硬件上的免费可用操作系统,将丰富的处理功能和能力提供给比以往更多的人,在比过去范围更广的系统上运行等等。信息处理的经济障碍的降低使强有力的数据库解决方案到达了比过去任何时候更多的人和机构的手中。例如,本人在运行 LinuxPPC 的 G3 PowerBook 笔记本电脑上使用 MySQL 与 Perl、Apache 和 PHP,这允许本人在任何地方都可以进行工作,总的成本只是 PowerBook 的成本。
过去只能梦想将高性能的 RDBMS 用于自己工作的机构,现在可以这样做了,并且开销很低。数据库的利用在单一的层次上也在不断地增加。过去从未想过要使用数据库的人现在也开始考虑一旦得到一个数据库,怎样将其用于自己的各种目的,例如用来存储和访问系统的研究结果,跟踪和维护最喜爱的收藏物(蝴蝶、邮票、捧球明星卡等等),帮助管理新开张的公司,或者提供个人 Web 站点的搜索能力。
1.1.2 我需要MySQL吗?
如果您正在寻找一种免费的或不昂贵的数据库管理系统,可以有几个选择,如,MySQL、mSQL、Postgres(一种免费的但不支持来自商业供应商引擎的系统)等。在将 MySQL 与其他数据库系统进行比较时,所要考虑的最重要的因素是性能、支持、特性(与 SQL 的一致性、扩展等等)、认证条件和约束条件、价格等。相比之下,MySQL 具有许多吸引人之处:
1、速度。MySQL 运行速度很快。开发者声称 MySQL 可能是目前能得到的最快的数据库。可访问 http://www.mysql.com/benchmark.html (MySQL Web 站点上的性能比较页),调查一下这个性能。
2、容易使用。MySQL 是一个高性能且相对简单的数据库系统,与一些更大系统的设置和管理相比,其复杂程度较低。
3、价格。MySQL 对多数个人用户来说是免费的。详细的信息请参阅本前言后面的 “MySQL是否免费”一节。
4、支持查询语言。MySQL 可以利用 SQL(结构化查询语言),SQL 是一种所有现代数据库系统都选用的语言。也可以利用支持 ODBC(开放式数据库连接)的应用程序,ODBC 是 Microsoft 开发的一种数据库通信协议。
5、性能。许多客户机可同时连接到服务器。多个客户机可同时使用多个数据库。可利用几个输入查询并查看结果的界面来交互式地访问 MySQL。这些界面为:命令行客户机程序、Web 浏览器或 X Window System 客户机程序。此外,还有由各种语言(如 C、Perl、Java、PHP 和 Python)编写的界面。因此,可以选择使用已编好的客户机程序或编写自己的客户机应用程序。
6、连接性和安全性。MySQL 是完全网络化的,其数据库可在因特网上的任何地方访问,因此,可以和任何地方的任何人共享数据库。而且 MySQL 还能进行访问控制,可以控制哪些人不能看到您的数据。
7、可移植性。MySQL 可运行在各种版本的 UNIX 以及其他非 UNIX 的系统(如 Windows 和 OS/2)上。MySQL 可运行在从家用 PC 到高级的服务器上。
如果,你对上面的特性非常在意,尤其是价格和速度、性能方面,那么我认为MySQL十分适合你。
1.1.3 我需要付钱吗?
基本上,我们许可证政策如下:
对于一般的内部使用,MySQL通常是免费的。如果你不想,就不必付钱给我们。
一个许可证是必需的,如果:
你直接销售MySQL服务器或作为其他产品或服务的一部分;
你在某些客户那里为了安装和维护一个 MySQL 服务器而收费;
你在不可再分发的分发中包括 MySQL并且你对该分发的某些部分收费;
在必须有 MySQL 许可证的情况下,对每台运行mysqld服务器的机器,你都需要一个许可证,但多CPU机器按单CPU计算,并且在一台机器上运行 MySQL 服务器的数量或并发连接到这台运行一个服务器的机器的客户数量也无限制!
你在商业程序中包含客户代码不需要一个许可证,MySQL的客户端存取部分不属公共领域,mysql命令行客户程序包含在 GNU 通用许可证下的 readline 库的代码。
对于已经购买了 10 个许可证或一种足够级别的技术支持的消费者,我们提供附加的功能。目前,这意味着我们提供 myisampack实用工具,它能生成快速的压缩的只读数据库(服务器支持读取这样的数据库,但不包含用于生成它们的压缩工具)。当支持协议产生了足够的收入时,我们将在与MySQL 服务器同样的许可证下发行这个工具。
如果你使用不需要一个许可证的 MySQL,但是你的确喜欢 MySQL 并且有志于更进一步的开发,无论如何肯定欢迎你购买一个许可证。
如果你在一个商业环境中使用 MySQL以便通过它获利,我们要求你购买一定级别的技术支持以推进开发。我们感到,如果 MySQL 有助于你的业务,要求你帮助MySQL也是合理的(否则,如果向我们你询问支持问题,你不仅是正在免费使用我们倾注大量精力的产品,而且你正在要求我们提供免费的支持。)。
对于在微软操作系统下面( Win95/Win98/WinNT)的使用,你在一个 30 天的试用期后需要一个 MySQL 许可证,除了教育用途或大学或政府资助的研究机构的许可证可免费申请获得,见 K 针对微软操作系统的 MySQL 许可证。一个共享软件版本的 MySQL -Win32 可在购买前从 http://www.mysql.com/mysql_w32.htmy 下载试用。在你付钱后,你将得到一个口令让你能够访问最新 MySQL - Win32 版本。
如果你需要一个 MySQL 许可证,最容易的付款方法是使用在 https://www.mysql.com/license.htmy网站的 Tcx 的安全服务器上的许可证表格。
1.1.4 如何得到MySQL?
在本小节读者不仅讲知道如何得到MySQL还将知道如何得到与MySQL有关的很多软件,虽然由于篇幅和本书写作目的的原因,我们不可能一一介绍它们:
从TcX公司的MySQL网站上http://www.mysql.com/doc.html你可以得到大部分需要的软件包:
MySQL分发包(包括各种平台——Windows、Linux等——,各种形式——二进制、源代码、RPM包——的分发),现在已经有适用GPL许可证的MySQL分发,请仔细阅读最新的许可信息。
MySQL 用于ODBC驱动程序MyODBC。
MySQL的JDBC驱动程序mm.mysql。
用PHP写成的客户程序phpMyAdmin。
以及其它各种第三方客户机。
获得Active Perl
http://www.activestate.com/
获得Perl DBI
http://www.symbolstone.org/technology/perl/DBI
获得PHP
www.php.net
获得Apache
http://www.apache.org
1.1.5总结
本节简单介绍的MySQL的方方面面,相信读者对MySQL已经有了一定的了解了。看看你是不是了解了它:
l MySQL是一个关系数据库系统,支持SQL查询语言。
l MySQL可以是免费的,你不需要为它付费。
l MySQL系统的速度非常快,同样它的性能也是十分优良的。
l MySQL是一个管理简捷的数据库,它没有庞大而臃肿的可视化管理工具。
1.2 关系数据库管理系统
在过去的许多年里,有许多关于“数据库”这个名词的定义。数据库是一个服务于一个核心目标的数据的有组织的集合。数据库中的数据是有组织的,从某种意义上说,数据库中存储的数据采用一种不变的方式被存储、格式化、存取以及显示。因为数据库不含有无关的或冗余的数据,它可以适用于一个核心目标。一本电话簿就是一个很好的数据库例子,它包含有关的数据(名字),让人们能够查找电话号码;它不包含无关的数据,如某人的电话机的颜色;它只贮存那些与它的目标相关的信息。最常见的,一个数据库的目标是商务应用,但是也可能贮存科学、军事或其他数据,这些数据通常不能当作商务数据看待。因此,有商业数据库、科学数据库、军事数据库以及其他的数据库等等。另外,数据不仅能根据它的应用分类,还能根据它的格式分类,现代数据库包括多种类型的数据。例如,现在数据库贮存图像、图表、声音、视频或包括两种或多种类型的复合文档,已经是很普通的事了。
1.2.1 关系数据库系统
所谓RDBMS,即关系数据库管理系统,
为了进一步了解一个RDBMS 是由什么构成的,你必须先了解关系模型。下列情况出现在一个关系模型中:
l 数据的基础项是关系。
l 在这些表上的操作只产生关系(关系型闭合)。
什么是关系?这是一个描述两个集合的元素如何相互联系或如何一一对应的数学概念。因此,关系模型是建立在数学基础上的。然而,对你来说,关系只是一个带有一些特殊属性的表,一个关系模型把数据组织到表中,而且仅在表中。客户、数据库设计者、数据库系统管理员和用户都以同样的方式—即从表中—查看数据。那么,表就是关系模型的近义词。
一个关系型表有一组命名的属性(a t t r i b u t e )或列,以及一组元组(t u p l e )或行。有时列被称为域,行被称为记录,列和行的交集通常被叫做单元。列标示位置,有作用域或数据类型,例如字符或整数。行自己就是数据。
一个关系表必须符合某些特定条件,才能成为关系模型的一部分:
1、贮存在单元中的数据必须是原子的。
每个单元只能存贮一条数据,这也叫信息原则(Information Principle )。尽管在过去的数年中按某些违反这一条的方式已经建立了许多系统,但违反这一条将不能运用良好的设计原则。当一个单元包含多于一条的信息时,这叫做信息编码(information coding )。在这样的情况下,是否采用违背理论的方案是一个设计的选择问题,尽管在多数情况下,结果证明这对数据的完整性是一不利的。
2、贮存在列下的数据必须具有相同数据类型。
3、每行是唯一的(没有完全相同的行)。
4、列没有顺序。
5、行没有顺序。
6、列有一个唯一性的名称。
除了表和它们的属性,关系模型有它自己特殊的操作。不需要深入研究关系型数学,只需说明这些操作可能包括列的子集、行的子集、表的连接以及其他数学集合操作(如联合)等就足够了。真正要知道的事情是这些操作把表当作输入,而将产生的表作为输出。
S Q L 是当前R D B M S 的A N S I 标准语言,它包含这些关系型操作。允许数据操作或数据处理的主要语句是S E L E C T 、I N S E RT 、U P D AT E 和D E L E T E 。因此,这些数据处理操作中任何一个都是一个事务。
允许数据定义或结构化处理的基本语句是C R E AT E 、A LT E R 和D R O P 。关系模型要求的最后一件事是两个基础的完整性原则。它们是实体完整性原则(e n t i t y integrity rule )和引用完整性原则(referential integrity rule )。首先,让我们看看两个定义:
1、主键(primary key )是能唯一标识行的一列或一组列的集合。有时,多个列或多组列可以被当作主键。
2、由多个列构成的主键被称为连接键(concatenated key )、组合键(compound key ),或者更常称为复合键(composite key )。
数据库设计者决定哪些列的组合能够最准确和有效地反映业务情形,这并不意味着其他数据未被存贮,只是那一组列被选作主键而已。
剩余有可能被选为主键的列被叫做候选键(candidate key )或替代键(alternate key )。一个外键(foreign key )是一个表中的一列或一组列,它们在其他表中作为主键而存在。一个表中的外键被认为是对另外一个表中主键的引用。实体完整性原则简洁地表明主键不能全部或部分地空缺或为空,引用完整性原则简洁地表明一个外键必须为空或者与它所引用的主键当前存在的值相一致。
一个R D B M S 就是一个建立在前面这些关系模型基础上的,一般能满足所提到的全部要求
的D B M S 。但是,在7 0 年代末到8 0 年代初,R D B M S 开始销售的时候,S Q L 超越了本质为非关系型的系统,受到普遍欢迎,并被称作关系型。
1.2.2 数据库系统的发展
1969年美国的IBM公司开发了第一个数据库系统IMS。这是一个层次数据库系统,在数据库系统发展史上有着重要的地位。同年,美国的数据系统语言委员会(CODASYL)下属的数据库任务组提出了著名的DBTG报告,并在1970年提出了该报告的修订版。这份报告定义了数据库操纵语言、模式定义语言和子模式定义语言的概念。数据库操纵语言用于编写操纵概念视图的应用程序,模式定义语言用来编写概念视图和内部视图相结合的模式程序。在七十年代,开发了许多遵循DBTG报告的网状数据库系统,如:IDMS, IDS, DMSIIOO等。七十年代初,E.F.Codd提出了关系数据模型的概念,提出了关系代数和关系演算。在整个七十年代,关系数据库从理论到实践都取得了辉煌成果。在理论上,确立了完整的关系理论、数据依赖理论以及关系数据库的设计理论等等;在实践上,开发了许多著名的关系数据库系统,如:system R, INGRES, ORACLE等。1986年美国国家标准协会(ANSI)通过了关系数据库查询语言SQL的文本标准。进入八十年代以后,随着计算机硬件技术的提,使得计算机应用不断深入,产生了许多新的应用领域,如:计算机辅助设计、计算机辅助教学、计算机辅助制造、计算机辅助工程、计算机集成制造、办公自动化、地理信息处理、智能信息处理等等。这些新的应用领域对数据库系统提出了新要求。由于没能设计出一个统一的数据模型来表示这些新型数据及其相互联系,所以出现了百家争鸣的局面,产生了演绎数据库(逻辑数据库,知识库)、面向对象数据库、工程数据库、时态数据库、地理数据库、模糊数据库、积极数据库、…等新型数据库的研究。到八十年代后期和九十年代初期,出现了面向对象数据库系统,如:GemStone, VBASE, ORION, Iris等。到目前为止,真正的新一代数据库系统还没有出现。
1.2.3 与数据库系统通讯
结构化查询语言(Structured Query Language ,SQL)是当今主要的查询语言,它主要用于管理主流类型的D B M S —关系型D B M S (R D B M S )。所有与数据库相关的通信往来都将通过D B M S 完成,为了做这件事,你可以使用S Q L 或其他类似的东西。数据库系统管理员(D B A )使用查询语言来建立并维护数据库,用户使用查询语言来访问数据库并查看或更改数据。
1.2.4 MySQL的体系结构
因为 MySQL 采用的是客户机/服务器体系结构,所以你在使用 MySQL 时存取数据时,必须至少使用两个或者说两类程序:
1、一个位于存放您的数据的主机上的程序——数据库服务器。数据库服务器监听从网络上传过来的客户机的请求并根据这些请求访问数据库的内容,以便向客户机提供它们所要求的信息。
2、连接到数据库服务器的程序——客户机,这些程序是用户和服务器交互的工具,告诉服务器需要什么信息的查询。
MySQL 分发包包括服务器和几个客户机程序。可根据要你要达到的目的来选择使用客户机。最常用的客户机程序为 mysql,这是一个交互式的客户机程序,它能发布查询并看到结果。其他的客户机程序有: mysqldump 和 mysqlimport,分别导出表的内容到某个文件或将文件的内容导入某个表;mysqladmin 用来查看服务器的状态并完成管理任务,如告诉服务器关闭、重起服务器、刷新缓存等。如果具有现有的客户程序不满足你的需要,那么MySQL还提供了一个客户机编程库,可以编写自己的程序。客户机编程库可直接从 C 程序中调用,如果希望使用 C 语言以外的其他语言,还有几种其他的接口可用。
MySQL 的客户机/服务器体系结构具有如下优点:
1、服务器提供并发控制,使两个用户不能同时修改相同的记录。所有客户机的请求都通过服务器处理,服务器分类辨别谁准备做什么,何时做。如果多个客户机希望同时访问相同的表,它们不必互相裁决和协商,只要发送自己的请求给服务器并让它仔细确定完成这些请求的顺序即可。
2、不必在数据库所在的机器上注册。MySQL 可以非常出色的在因特网上工作,因此您可以在任何位置运行一个客户机程序,只要此客户机程序可以连接到网络上的服务器。
当然不是任何人都可以通过网络访问你的MySQL服务器。MySQL 含有一个灵活而又有成效的安全系统,只允许那些有权限访问数据的人访问。而且可以保证用户只能够做允许他们做的事。
1.2.5总结
本节简单介绍了一下关系数据库系统的基础知识,真正要详尽描述数据库系统的理论,完全可以写成几本书。读完本节之后,笔者希望读者能够了解什么是关系模型、SQL语言以及MySQL的系统结构,这不仅对继续阅读本书有利,也可以在读者获取相关知识时,起到一个启发的作用。
1.3 MySQL使用的SQL语言
MySQL使用结构化查询语言(Structured Query Language,SQL)与服务器通讯。MySQL系统使用的SQL语言基本上符合SQL92的标准,但是其对SQL92标准既有扩展,又有未实现的地方。
1.3.1 表、列和数据类型
表是数据在一个MySQL数据库中的存储机制,如表1-1所示,它包含一组固定的列。表中的列描述该表所跟踪的实体的属性,每个列都有一个名字及各自的特性。
列由两部分组成:数据类型(datatype)和长度(length)。对于使用NUMERIC 数据类型的列,可以指定列的小数位及精度特性,精度决定数值的有效位数,小数位表示数值的小数点位置。说明为NUMERIC(9,2)的列表示该列总共有9位数,其中2位数在小数点右边。缺省的数值精度为10位数。
表1-1 一个数据表techers
|
Id |
Name |
Tel |
Sex |
|
1 |
Tom |
62763218 |
M |
|
2 |
Marry |
21532777 |
F |
|
3 |
Mike |
45769021 |
M |
|
4 |
Jerry |
3245012 |
M |
|
… |
… |
… |
… |
注意,在上表中你可能会有每行记录是按顺序记录的印象,假设你想取出表中的前十个记录。使用传统的编程语言,你可以做一个循环,取出前十个记录后结束循环。但使用标准的SQL查询,这是不可能实现的。因为在关系数据模型中,记录就是行是没有顺序的,也就是说,在一个表中不存在前十个记录这种概念。
1.3.2函数
函数(function)是存储在数据库中的代码块。其差别在于函数可以把值返回调用程序。你可以建立自己的函数,并在SQL语句中调用它们,就像执行Oracle提供的函数一样。例如,MySQL提供一个SUBSTRING函数来执行字符串上的“取子串”操作,如果创建一个叫做MYSUB的函数来执行一个自定义的取子串操作,就可以在一个SQL命令中调用它:
SELECT MYSUB("This is a test",6,2)
1.3.3 SQL的语句
SQL是一种典型的非过程化程序设计语言,这种语言的特点是:只指定哪些数据被操纵,至于对这些数据要执行哪些操作,以及这些操作是如何执行的,则未被指定。非过程化程序设计语言的优点在于它的简单易学,因此已经成为关系数据库访问和操纵数据的标准语言。
与之相对应的是过程化程序设计语言,我们平常熟悉的各种高级程序设计语言都属于这一范畴。这种语言的特点是:一条语句的执行是与其前后的语句和控制结构(如条件语句、循环语句等)相关的。与SQL相比,这些语言显得比较复杂,但优点是使用灵活,数据操纵能力非常强大。
这种语言被设计为不允许你按照某种特定的顺序来取出记录,因为这样做会降低SQL Sever取记录的效率。使用SQL,你只能按查询条件来读取记录。
当考虑如何从表中取出记录时,自然会想到按记录的位置读取它们。例如,也许你会尝试通过一个循环,逐个记录地扫描,来选出特定的记录。在使用SQL时,你必须训练自己,不要有这种思路。
假如你想选出所有的名字是“Tom”的记录,如果使用传统的编程语言,你也许会构造一个循环,逐个查看表中的记录,看名字域是否是“Tom”。
这种选择记录的方法是可行的,但是效率不高。使用SQL,你只要说,“选择所有名字域等于Tom的记录”,SQL就会为你选出所有符合条件的记录。SQL会确定实现查询的最佳方法。
例如,我们从表1-1中取出id为1的数据:
SELECT * FROM teachers WHERE id=1
相同的功能用普通的高级语言,也许需要一个复杂的循环。
1.3.4总结
在这一节中,简单介绍了SQL查询语言的基本知识,对于列数据类型、SQL的各种语句,将在以后的章节中介绍,这是一个很长的过程。
1.4 MySQL数据处理
MySQL支持大量的列类型,它可以被分为3类:数字类型、日期和时间类型以及字符串(字符)类型。本节首先给出可用类型的一个概述,并且总结每个列类型的存储需求,然后提供每个类中的类型性质的更详细的描述。概述有意简化,更详细的说明应该考虑到有关特定列类型的附加信息,例如你能为其指定值的允许格式。
1.4.1 MySQL的数据
MySQL有几种数据类型,你应该了解它们是怎么使用的:
1.4.1.1、字符串值
字符串是类似”I like mysql.”和’MySQL is powerful.’等这样的值,它们既可以用双引号括起来,也可以是用单引号。
在字符串中不仅可以使用普通的字符,也可使用几个转义序列,它们用来表示特殊的字符,见表 1-2。每个转义序列以一个反斜杠(“\”)开始,指出后面的字符使用转义字符来解释,而不是普通字符。注意 NUL 字节与 NULL 值不同;NUL 为一个零值字节,而 NULL 代表没有值。
表1-2 字符串转移序列表
|
序列 |
涵义 |
|
\0 |
一个ASCII 0 (NUL)字符 |
|
\n |
一个新行符 |
|
\r |
一个回车符(Windows中使用\r\n作为新行标志) |
|
\t |
一个定位符 |
|
\b |
一个退格符 |
|
\’ |
一个单引号(“\'”)符 |
|
\” |
一个双引号(“"”)符 |
|
\\ |
一个反斜线(“\”)符 |
|
\% |
一个“%”符。它用于在正文中搜索“%”的文字实例,否则这里“%”将解释为一个通配符 |
|
\_ |
一个“_”符。它用于在正文中搜索“_”的文字实例,否则这里“_”将解释为一个通配符 |
现在需要注意的是,如何在串中使用引号,你可以有多种办法:
l 如果串是用相同的引号括起来的,那么在串中需要引号的地方重复写该引号即可。
l 如果串是用另外的引号括起来的,则不需要双写相应引号,直接在串中使用,该引号不被特殊对待。
l 使用反斜杠,用转移序列的方式表示;这种方法不去管用来将串括起的是单引号还是双引号。
例如,下面语句的结果是:
mysql> SELECT \'hello\', \'"hello"\', \'""hello""\', \'hel\'\'lo\', \'\\'hello\';
+-------+---------+-----------+--------+--------+
| hello | "hello" | ""hello"" | hel\'lo | \'hello |
+-------+---------+-----------+--------+--------+
1.4.1.2数字值
MySQL中的数字是类似于100或3.1215936这样的值。MySQL 支持说明为整数(无小数部分)或浮点数(有小数部分)的值:
l 整数由数字序列组成。浮点数由一个阿拉伯数字序列、一个小数点和另一个阿拉伯数字序列组成。两个阿拉伯数字序列可以分别为空,但不能同时为空。
l MySQL 支持科学表示法。科学表示法由整数或浮点数后跟“e”或“E”、一个符号(“+”或“-”,必须具有)和一个整数指数来表示。
l 数值前可放一个负号“-”以表示负值。
例如,下面都是合法的数值:
整数值:1221 0 -32
浮点数:294.42 -32032.6809e+10 148.
下面的值是错误的:
1.34E12
1.4.1.3十六进制值
MySQL支持十六进制值。以十六进制形式表示的整数由“0x”后跟一个或多个十六进制数字(”0”到“9”及“a”到“f”)组成。例如,0x0a 为十进制的 10,而 0xffff 为十进制的 65535。十六进制数字不区分大小写,但其前缀“0x”不能为“0X”。即 0x0a 和 0x0A 都是合法的,但 0X0a 和 0X0A 不是合法的。
在数字上下文,它们表现类似于一个整数(64位精度)。在字符串上下文,它们表现类似于一个二进制字符串,这里每一对十六进制数字被变换为一个字符。
例如:
mysql> select 0x5061756c+0, 0x5061756c;
其结果为:
+--------------+------------+
| 0x5061756c+0 | 0x5061756c |
+--------------+------------+
| 1348564332 | Paul |
+--------------+------------+
1.4.1.4日期和时间值
日期和时间值是一些类似于“1999-06-17”或“12:30:43”这样的值。MySQL 还支持日期/时间的组合,如“1999-06-17 12:30:43”。
需要要特别注意的是,MySQL 是按年-月-日的顺序表示日期的。这可能与你学过的高级语言不同。
1.4.1.4 NULL值
NULL值可适用于各种列类型,它通常用来表示“没有值”、 “无数据”等意义,并且不同于例如数字类型的0为或字符串类型的空字符串。
1.4.2列类型概述
数据库中的每个表都是由一个或多个列构成的。可以用 CREATE TABLE 语句创建一个表,创建表时要为每列指定一个类型。列的类型与数据类型相对应,但是比数据类型更为具体,用列类型描述表列可能包含的值的种类以及范围,列的值必须符合规定,不能包含对应的数据类型所允许的所有值。例如,CHAR(16)就规定了存储的字符串值必须是16位。当然不是你必须存储16个字符,而是指列在表中要占16个字符的宽度的。
MySQL的列类型是一种手段,通过这种手段可以描述一个表列包含什么类型的值,这又决定了 MySQL 怎样处理这些值。例如,数值值既可用数值也可用串的列类型来存放,但是根据存放这些值的类型,MySQL 对它们的处理将会有些不同。每种列类型都有几个特性如下:
l 其中可以存放什么类型的值。
l 值要占据多少空间,以及该值是否是定长的(所有值占相同数量的空间)或可变长的(所占空间量依赖于所存储的值)。
l 该类型的值怎样比较和存储。
l 此类型是否允许 NULL 值。
l 此类型是否可以索引。
下面是创建一个表的例子:
CREATE TABLE teacher
(
id TINYINT UNSIGNED NOT NULL,
name CHAR(16) NOT NULL,
tele NUMERIC(8),
sex ENUM("F","M") DEFAULT "M"
)
由上面这个例子可以知道,创建列类型的语法是:
col_name col_type [col_attributes][general_attributes]
l col_name 列的名字
l col_type 列类型,控制存储在列中的数据类型
l col_attributes 专用属性,只能应用于制定列,例如,我们还不知道的BINARY。如果你使用专用属性,必须在列的类型之后,列的通用属性之前。
l general_attributes通用属性,可以应用在出少数列的任意列,例如上面提到了NULL、NOT NULL、和DEFAULT。
我们将简要地考察一下 MySQL列类型以获得一个总的概念,然后更详细地讨论描述每种列类型的属性。
MySQL的数字类型如表1-3所示,可以包括浮点类型和整数类型:
表1-3 MySQL的数字列类型
|
类型名 |
涵义 |
|
TINYINT |
一个很小的整数 |
|
SMALLINT |
一个小整数 |
|
MEDIUMINT |
一个中等大小整数 |
|
INT、INTEGER |
一个正常大小整数 |
|
BIGINT |
一个大整数 |
|
FLOAT |
一个小(单精密)浮点数字 |
|
DOUBLE DOUBLE PRECISION REAL |
一个正常大小(双精密)浮点数字 |
|
DECIMAL NUMERIC |
一个未压缩(unpack)的浮点数字,“未压缩”意味着数字作为一个字符串被存储 |
MySQL的字符串类型如表1-4所示,串类型中不仅可以存储字符串,实际上任何二进制数据,例如,图象、音频、视频等,都可以存储在串类型中。
表1-4 MySQL的字符串列类型
|
类型名 |
涵义 |
|
CHAR |
一个定长字符串 |
|
VARCHAR |
一个变长字符串 |
|
TINYBLOB TINYTEXT |
最大长度为255(2^8-1)个字符的BLOB或TEXT列 |
|
BLOB TEXT |
最大长度为65535(2^16-1)个字符的BLOB或TEXT列 |
|
MEDIUMBLOB MEDIUMTEXT |
最大长度为16777215(2^24-1)个字符的BLOB或TEXT列 |
|
LONGBLOB LONGTEXT |
最大长度为4294967295(2^32-1)个字符的BLOB或TEXT列 |
|
ENUM(\'value1\',\'value2\',...) |
枚举:列只能赋值为某个枚举成员或NULL |
|
SET(\'value1\',\'value2\',...) |
集合:列可以赋值为多个集合成员或NULL |
MySQL的日期与时间类型如表1-5所示。MySQL允许你存储某个“不严格地”合法的日期值,例如1999-11-31,原因我们认为它是应用程序的责任来处理日期检查,而不是SQL服务器。为了使日期检查更“快”,MySQL仅检查月份在0-12的范围,天在0-31的范围。
表1-5 MySQL的时间和日期列类型
|
类型名 |
涵义 |
|
DATE |
一个日期,以\'YYYY-MM-DD\'格式来显示 |
|
TIME |
一个日期和时间组合,以\'YYYY-MM-DD HH:MM:SS\'格式来显示 |
|
DATETIME |
最大长度为255(2^8-1)个字符的BLOB或TEXT列 |
|
TIMESTAMP |
一个时间戳, 以YYYMMDDHHMMSS格式来显示 |
1.4.3 数字列类型
MySQL支持所有的ANSI/ISO SQL92的数字类型。这些类型包括准确数字的数据类型(NUMERIC, DECIMAL, INTEGER,和SMALLINT),也包括近似数字的数据类型(FLOAT, REAL,和DOUBLE PRECISION)。关键词INT是INTEGER的一个同义词,而关键词DEC是DECIMAL一个同义词。
MySQL的数字列类型有两种:
l 整型 MySQL提供了五种整型TINYINT、SAMLLINT、MEDIUMINT、INT和BIGINT。整数列可以用UNSIGNED禁用负数值。
l 浮点型 MySQL提供了三种浮点型,FLOAT、DOUBLE和DECIMAL。
下面,我们将详细描述数字类型的定义,取值范围和存储要求。
1.4.3.1整数类型
MySQL支持所有的ANSI/ISO SQL92的数字类型,其中的整数类型为INTEGER,和SMALLINT,关键词INT是INTEGER的一个同义词:
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
取值范围:有符号:-32768到32767(-215到215-1)无符号:0到65535(0到216-1)
存储要求:2个字节
INT[(M)] [UNSIGNED] [ZEROFILL]、INTEGER[(M)] [UNSIGNED] [ZEROFILL]
取值范围:有符号:-2147483648到2147483647(-231到231-1)无符号:0到4294967295(0到232-1)
存储要求:4个字节
作为对ANSI/ISO SQL92标准的扩展,MySQL也支持上表所列的整型类型TINYINT、MEDIUMINT和BIGINT:
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
取值范围:有符号:-128到127(-27和27-1)无符号:0到255(0到28-1)
存储要求:1个字节
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
取值范围:有符号:-8388608到8388607(-223到223-1)无符号:0到16777215(0到224-1)
存储要求:3个字节
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
取值范围:有符号:-9223372036854775808到9223372036854775807(-263到263-1)无符号:0到18446744073709551615(0到264-1)
存储要求: 8个字节
在为列选择了使用某种数值类型时,除了要考虑数据的类型外,还应该注意所要表示的值的范围和存储需求,只需选择能覆盖要取值的范围的最小类型即可。选择较大类型会对空间造成浪费,使表不必要地增大,处理起来没有选择较小类型那样有效。对于整型值,如果数据取值范围较小,则TINYINT最合适。MEDIUMINT和INT虽然能表示能够表示更大的数值并且可用于更多类型的值,但存储代价更大。BIGINT 在全部整型中取值范围最大,而且需要的存储空间是表示范围次大的整型 INT 类型的两倍,因此只在确实需要时才用。
作为对ANSI/ISO SQL92标准的的另一个扩展, MySQL支持可选地指定一个整型值显示的宽度,用括号跟在基本关键词之后(例如,INT(4))。这个可选的宽度指定被用于其宽度小于列指定宽度的值得左填补显示,但是不限制能在列中被存储的值的范围;如果某个特定值的可打印表示需要不止 M 个字符,则显示完全的值;不会将值截断以适合 M 个字符。当与可选的扩展属性ZEROFILL一起使用时,缺省的空格填补用零代替。例如,对于声明为INT(5) ZEROFILL的列,一个为4的值作为00004被检索。如果定义了一个没有明确宽度的整数列,将会自动分配给它一个缺省的宽度。缺省值为每种类型的“最长”值的长度。
我们可以这样知道M和D的缺省值。先创建一个表
CREATE TABLE number
(
tiny TINYINT,u_tiny TINYINT UNSIGNED,
small SMALLINT,u_small SMALLINT UNSIGNED,
medium MEDIUMINT,u_medium MEDIUMINT UNSIGNED,
num INT,u_num INT UNSIGNED,
big BIGINT,u_big BIGINT UNSIGNED
)
然后显示这个表的结构
DESCRIBE number
在MySQL3.23上的结果如下:
+----------+-----------------------+
| Field | Type |
+----------+-----------------------+
| tiny | tinyint(4) |
| u_tiny | tinyint(3) unsigned |
| small | smallint(6) |
| u_small | smallint(5) unsigned |
| medium | mediumint(9) |
| u_medium | mediumint(8) unsigned |
| num | int(11) |
| u_num | int(10) unsigned |
| big | bigint(20) |
| u_big | bigint(20) unsigned |
+----------+-----------------------+
1.4.3.2浮点数类型
MySQL支持所有的ANSI/ISO SQL92的浮点数字类型。这些类型包括准确数字的数据类型(NUMERIC, DECIMAL),也包括近似数字的数据类型(FLOAT, REAL,和DOUBLE PRECISION)。关键词DEC是DECIMAL一个同义词:
FLOAT[(M,D)] [ZEROFILL]
取值范围:-3.402823466E+38到-1.175494351E-38,0 和1.175494351E-38到3.402823466E+38
存储要求:4个字节
DOUBLE[(M,D)] [ZEROFILL]、DOUBLE PRECISION[(M,D)] [ZEROFILL]
取值范围:-1.7976931348623157E+308到-2.2250738585072014E-308、 0和2.2250738585072014E-308到1.7976931348623157E+308
存储要求:8个字节
DECIMAL(M[,D]) [ZEROFILL]、NUMERIC(M[, D]) [ZEROFILL]
取值范围:实际的范围可以通过M和D的选择被限制
存储要求:M字节(低于3.23版本)M+2字节(3.23或更高版本)
NUMERIC和DECIMAL类型
表1-6 M和D对DECIMAL类型取值范围的影响
|
类 型 说 明 |
取值范围(MySQL < 3.23) |
取值范围(MySQL * 3.23) |
|
DECIMAL(4, 1) |
-9.9 到 99.9 |
-999.9 到 9999.9 |
|
DECIMAL(5, 1) |
-99.9 到 999.9 |
-9999.9 到 99999.9 |
|
DECIMAL(6, 1) |
-999.9 到 9999.9 |
-99999.9 到 999999.9 |
|
DECIMAL(6, 2) |
-99.99 到 999.99 |
-9999.99 到 99999.99 |
|
DECIMAL(6, 3) |
-9.999 到 99.999 |
-999.999 到 9999.999 |
给定的 DECIMAL 类型的取值范围取决于MySQL 的版本。
对于 MySQL 3.23 以前的版本,DECIMAL(M, D) 列的每个值占用 M 字节,而符号(如果需要)和小数点包括在 M 字节中。因此,类型为 DECIMAL(5,2) 的列,其取值范围为 -9.99 到 99.99,因为它们覆盖了所有可能的 5 个字符的值。
对于MySQL 3.23,DECIMAL 值是根据 ANSI 规范进行处理的,ANSI 规范规定 DECIMAL(M, D) 必须能够表示 M 位数字及 D 位小数的任何值。例如,DECIMAL(5, 2) 必须能够表示从 -999.99 到 999.99 的所有值。而且必须存储符号和小数点,因此自 MySQL 3.23 以来 DECIMAL 值占 M + 2 个字节。对于 DECIMAL(5, 2),“最长”的值(-999.99)需要 7 个字节。在正取值范围的一端,不需要正号,因此 MySQL 利用它扩充了取值范围,使其超过了 ANSI 所规范所要求的取值范围。如 DECIMAL(5, 2) 的最大值为 9999.99,因为有 7 个字节可用。
简而言之,在MySQL 3.23 及以后的版本中,DECIMAL(M, D) 的取值范围等于更早版本中的 DECIMAL(M + 2, D) 的取值范围。
1.4.4 日期和时间类型
MySQL提供几种时间和日期类型,包括日期和时间类型是DATETIME、DATE、TIMESTAMP、TIME和YEAR。对这几种时间和日期类型概述如下:
DATA
取值范围:“1000-01-01”到“9999-12-31”
存储需求:3字节
TIME
取值范围:“-838:59:59”到“838:59:59”
存储需求:3字节
DATATIME
取值范围:“1000-01-01 00:00:00”到“9999-12-31 23:59:59”
存储需求:8字节
TIMESTAMP[(M)]
取值范围:“19700101000000”到2037年的某个时刻
存储需求:4字节
YEAR[(M)]
取值范围:1901到2155
存储需求:1字节
1.4.4.1 Y2K问题和日期类型
MySQL本身Y2K安全的,但是呈交给MySQL的输入值可能不是。一个包含2位年份值的任何输入是由二义性的,因为世纪是未知的。这样的值必须被解释成4位形式,因为MySQL内部使用4位存储年份。
对于DATETIME, DATE, TIMESTAMP和YEAR类型,MySQL使用下列规则的解释二义性的年份值:
l 在范围00-69的年值被变换到2000-2069。
l 在范围70-99的年值被变换到1970-1999。
记得这些规则仅仅提供对于你数据的含义的合理猜测。如果MySQL使用的启发规则不产生正确的值,你应该提供无二义的包含4位年值的输入。
1.4.4.2 DATETIME,DATE和TIMESTAMP类型
DATETIME, DATE和TIMESTAMP类型是相关的。本节描述他们的特征,他们是如何类似的而又不同的。
DATETIME类型用在你需要同时包含日期和时间信息的值时。MySQL检索并且以\'YYYY-MM-DD HH:MM:SS\'格式显示DATETIME值,支持的范围是\'1000-01-01 00:00:00\'到\'9999-12-31 23:59:59\'。(“支持”意味着尽管更早的值可能工作,但不能保证他们可以。)
DATE类型用在你仅需要日期值时,没有时间部分。MySQL检索并且以\'YYYY-MM-DD\'格式显示DATE值,支持的范围是\'1000-01-01\'到\'9999-12-31\'。
TIMESTAMP列类型提供一种类型,你可以使用它自动地用当前的日期和时间标记INSERT或UPDATE的操作。如果你有多个TIMESTAMP列,只有第一个自动更新。TIMESTAMP值可以从1970的某时的开始一直到2037年,精度为一秒,其值作为数字显示。
自动更新第一个TIMESTAMP列在下列任何条件下发生:
l 列没有明确地在一个INSERT或LOAD DATA INFILE语句中指定。
l 列没有明确地在一个UPDATE语句中指定且一些另外的列改变值。(注意一个UPDATE设置一个列为它已经有的值,这将不引起TIMESTAMP列被更新,因为如果你设置一个列为它当前的值,MySQL为了效率而忽略更改。)
l 你明确地设定TIMESTAMP列为NULL.
例如,我们创建一个表:
CREATE TABLE my_test
(
id INT,
ts TIMESTAMP
)
然后,用如下语句录入数据:
INSERT my_test VALUES(1,20010101000000)
INSERT my_test(id) VALUES(2)
然后,查询表中的内容:
SELECT * from my_test
你可以看到内容:
+------+----------------+
| id | ts |
+------+----------------+
| 1 | 20010101000000 |
| 2 | 20010113165713 |
+------+----------------+
1.4.4.3 TIME类型
MySQL检索并以\'HH:MM:SS\'格式显示TIME值(或对大小时值,\'HHH:MM:SS\'格式)。TIME值的范围可以从\'-838:59:59\'到\'838:59:59\'。小时部分可能很大的的原因是TIME类型不仅可以被使用在表示一天的时间(它必须是不到24个小时),而且用在表示在2个事件之间经过的时间或时间间隔(它可以是比24个小时大些,或甚至是负值)。
你能用多中格式指定TIME值:
l 作为\'HH:MM:SS\'格式的一个字符串。“宽松”的语法被允许--任何标点符号可用作时间部分的分隔符,例如,\'10:11:12\'和\'10.11.12\'是等价的。
l 作为没有分隔符的\'HHMMSS\'格式的一个字符串,如果它作为一个时间解释。例如,\'101112\'被理解为\'10:11:12\',但是\'109712\'是不合法的(它有无意义的分钟部分)并变成\'00:00:00\'。
l 作为HHMMSS格式的一个数字,如果它能解释为一个时间。例如,101112被理解为\'10:11:12\'。
1.4.4.4 YEAR类型
YEAR类型是一个有效的利用1字节类型表示年份。MySQL检索并且以YYYY格式显示YEAR值,其范围是1901到2155。 如果,只想保存日期,那么YEAR比其它类型比如SAMLLINT更为有效。
你能用多种格式指定YEAR值,既可以用4为字符,也可以使用4为字符串,当然要在1901到2155范围之内。
作为YEAR的一个优点是,你可以指定一个在\'00\'到\'99\'范围的2位字符串或者一个在\'00\'到\'69\'和\'70\'到\'99\'范围的值被变换到在2000到2069范围和1970到1999的YEAR值。
1.4.5 字符串类型
MySQL提供的字符串类型包括CHAR、VARCHAR、BLOB、TEXT、ENUM和SET。对这些类型作一个简要的叙述如下:
CHAR(M) [BINARY]
一个定长字符串,当存储时,总是是用空格填满右边到指定的长度。在MySQL3.23以前的版本,M的范围是1 ~ 255个字符,在MySQL3.23版中,M值的范围是0 ~ 255个字符.当值被检索时,空格尾部被删除。CHAR类型在排序和比较时不区分大小写,除非给出BINARY关键词。NATIONAL CHAR(短形式NCHAR)是ANSI SQL的方式来定义CHAR列应该使用缺省字符集。这是MySQL的缺省。CHAR是CHARACTER的一个缩写。 CHAR(0) 可以用于在希望定义一个列,但由于尚不知道其长度,所以不想给其分配空间的情况下,CHAR(0) 列作为占位符很有用处。以后可以用 ALTER TABLE 来加宽这个列。
存储需求:M字节
[NATIONAL] VARCHAR(M) [BINARY]
一个变长字符串。注意:当值被存储时,尾部的空格被删除(这不同于ANSI SQL规范)。M的范围是1 ~ 255个字符。 VARCHAR类型在排序和比较时不区分大小写,除非给出BINARY关键词。VARCHAR是CHARACTER VARYING一个缩写。
存储需求:L+1字节(L是存储实际值需要的长度,1为存储该值实际长度)
TINYBLOB、TINYTEXT
一个BLOB或TEXT列,最大长度为255(2^8-1)个字符。
存储需求:L+1字节
BLOB、TEXT
一个BLOB或TEXT列,最大长度为65535(2^16-1)个字符。
存储需求:L+2字节
MEDIUMBLOB、MEDIUMTEXT
一个BLOB或TEXT列,最大长度为16777215(2^24-1)个字符。
存储需求:L+3字节
LONGBLOB、LONGTEXT
一个BLOB或TEXT列,最大长度为4294967295(2^32-1)个字符。
存储需求:L+4字节
ENUM(\'value1\',\'value2\',...)
枚举。一个仅有一个值的字符串对象,这个值式选自与值列表\'value1\'、\'value2\', ...,或NULL。一个ENUM最多能有65535不同的值。
存储需求:1或2字节
SET(\'value1\',\'value2\',...)
一个集合。能有零个或多个值的一个字符串对象,其中每一个必须从值列表\'value1\', \'value2\', ...选出。一个SET最多能有64个成员。
存储需求:1、2、3、4或8字节
在某种意义上,串实际是一种非常“通用”类型,因为可用它们来表示任意值,不仅仅是字符串。例如,可用串类型来存储二进制数据,如图像、视频或音频。
对于所有串类型,都要剪裁过长的值使其适合于相应的串类型。但是串类型的取值范围很不同,有的取值范围很小,有的则很大。取值大的串类型能够存储近 4GB 的数据。因此,应该使串足够长以免您的信息被切断(由于受客户机/服务器通信协议的最大块尺寸限制,列值的最大限额为 24MB)。
另外,对于串类型,在比较时是忽略大小写的,使用BINARY关键字,则比较时采用ASCII码的方式,即不再忽略大小写。可以使用BINARY的串类型为CHAR和VARCHAR。
1.4.5.1 CHAR和VARCHAR类型
CHAR和VARCHAR类型是类似的,但是在他们被存储和检索的方式不同。 其具体的异同为:
l 当给定一个CHAR列的值时,其长度将被被修正为在你创建表时所声明的长度。长度可以是1和255之间的任何值。(在MySQL 3.23中,CHAR长度可以是0~255。) 当CHAR值被存储时,他们被用空格在右边填补到指定的长度。当CHAR值被检索时,拖后的空格被删去。
l 在VARCHAR列中的值是变长字符串。你可以声明一个VARCHAR列是在1和255之间的任何长度,就像对CHAR列。然而,与CHAR类型相反,VARCHAR值只存储所需的字符,外加一个字节记录长度,值不被填补;相反,当值被存储时,拖后的空格被删去。(这个空格删除不同于ANSI SQL规范。)
l 如果你把一个超过列最大长度的值赋给一个CHAR或VARCHAR列,值被截断以适合串类型。
例如,我们用下表来说明存储一系列不同的串值到CHAR(4)和VARCHAR(4)列的结果:
表1-7 CHAR类型和VARCHAR类型的对比
|
值 |
CHAR(4) |
存储需求 |
VARCHAR(4) |
存储需求 |
|
\'\' |
\' \' |
4字节 |
\'\' |
1字节 |
|
\'ab\' |
\'ab \' |
4字节 |
\'ab\' |
3字节 |
|
\'abcd\' |
\'abcd\' |
4字节 |
\'abcd\' |
5字节 |
|
\'abcdefgh\' |
\'abcd\' |
4字节 |
\'abcd\' |
5字节 |
虽然实际存储的值并不一样,但是查询时,这两种类型是一致的,因为CHAR(4)类型多于的空格将被忽略。
需要注意的是,除了少数情况外,在同一个表中不能混用 CHAR 和 VARCHAR这两种类型,你只能使用其中之一。如果你创建表时,包括这两种类型,在一般情况下,MySQL 会将列从一种类型转换为另一种类型。这样做的原因如下:
l 行定长的表比行可变长的表容易处理,效率更高。
l 只有所有的类型是定长时,行才是定长的,才能提高性能。
l 有时为了节省存储空间,使用了变长类型,在这种情况下最好也将定长列转换为可变长列。
这表示,如果表中有 VARCHAR 列,那么表中不可能同时有 CHAR 列;MySQL 会自动地将它们转换为 VARCHAR 列。
转换的规则:
l 长度小于4的VARCHAR被改变为CHAR。
l 如果在一个表中的任何列有可变长度,结果是整个行是变长的。因此, 如果一张表包含任何变长的列(VARCHAR、TEXT或BLOB),所有大于3个字符的CHAR列被改变为VARCHAR列。
例如,我们创建下面一个表:
CREATE TABLE ch_type
(
ch1 char(3),
ch2 varchar(3),
ch3 char(4),
ch4 varchar(4)
)
然后查看表的结构:
DESCRIBE ch_type
在MySQL3.23上结果为:
+-------+------------+
| Field | Type |
+-------+------------+
| ch1 | char(3) |
| ch2 | char(3) |
| ch3 | varchar(4) |
| ch4 | varchar(4) |
+-------+------------+
1.4.5.2 BLOB和TEXT类型
一个BLOB是一个能保存可变数量的数据的二进制的大对象。4个BLOB类型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB仅仅在他们能保存值的最大长度方面有所不同。
4个TEXT类型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT对应于4个BLOB类型,并且有同样的最大长度和存储需求。在BLOB和TEXT类型之间的唯一差别是对BLOB值的排序和比较以大小写敏感方式执行,而对TEXT值是大小写不敏感的。换句话说,一个TEXT是一个大小写不敏感的BLOB。
如果你把一个超过列类型最大长度的值赋给一个BLOB或TEXT列,值被截断以适合它。
在大多数方面,你可以认为一个TEXT行列是你所希望大的一个VARCHAR列。同样,你可以认为一个BLOB列是一个VARCHAR BINARY列。差别是:
l 用MySQL版本3.23.2和更新,你能在BLOB和TEXT列上索引。更旧的MySQL版本不支持这个。
l 当值被存储时,对BLOB和TEXT列没有拖后空格的删除,因为对VARCHAR列有删除。
l BLOB和TEXT列不能有DEFAULT值。
由于,BLOB和TEXT类型可以存储非常多的数据,因此使用BLOB和TEXT类型需要注意的是:
l BLOB 或 TEXT 列在 MySQL 3.23 以上版本中可以进行索引,虽然在索引时必须指定一个用于索引的约束尺寸,以免建立出很大的索引项从而抵消索引所带来的好处。
l 由于 BLOB 和 TEXT 值的大小变化很大,如果进行的删除和更新很多,则存储它们的表出现高碎片率会很高。应该定期地运行 OPTIMIZE TABLE 减少碎片率以保持良好的性能。
1.4.5.3 ENUM和SET类型
1、ENUM和SET类型的定义
ENUM和SET类型是两种特殊的字符串类型,它们有很多相似之处,使用方法也是分类系,通常都从一个在表创建时明确列举的允许值的一张表中选择,其主要的区别是ENUM列必须是值集合中的一个成员,而SET列可以包括其中的任意成员。
例如,创建如下两个串列:
color ENUM(“red”,”black”,”green”,”yellow”)
property SET(“car”,”house”,”stock”) NOT NULL
那么color和property可能的值分别为:
color:NULL、”red”、”black”、”green”和”yellow”
而property可能的值就复杂的多:
“”
“car”
“house”
“car,house”
“stock”
“car,stock”
“house,stock”
“car,house,stock”
由于空串可以表示不具备值的集合的任何一个值,所以这也是一个合法的SET值。
ENUM类型可以有65536个成员,而SET类型最多可以有64个成员。
2、ENUM和SET类型是如何存储的
ENUM和SET类型在数据库内部并不是用字符的方式存储的,而是使用一系列的数字,因此更为高效。
ENUM和SET类型的合法值列表的原则为:
l 此列表决定了列的可能合法值。
l 可按任意的大小写字符插入 ENUM 或 SET 值,但是列定义中指定的串的大小写字符决定了以后检索它们时的大小写。
l 在 ENUM 定义中的值顺序就是排序顺序。SET 定义中的值顺序也决定了排序顺序,但是这个关系更为复杂,因为列值可能包括多个集合成员。
l SET 定义中的值顺序决定了在显示由多个集合成员组成的 SET 列值时,子串出现的顺序。
对于ENUM列类型,成员是从 1 开始顺序编号的。(0 被 MySQL 用作错误成员,如果以串的形式表示就是空串。)枚举值的数目决定了 ENUM 列的存储大小。一个字节可表示 256 个值,两个字节可表示 65 536 个值。因此,枚举成员的最大数目为 65 536(包括错误成员),并且存储大小依赖于成员数目是否多于 256 个。在 ENUM 定义中,可以最多指定 65 535(而不是 65 536)个成员,因为 MySQL 保留了一个错误成员,它是每个枚举的隐含成员。在将一个非法值赋给 ENUM 列时,MySQL 自动将其换成错误成员。
对于SET类型,SET 列的集合成员不是顺序编号的,而是每个成员对应 SET 值中的一个二进制位。第一个集合成员对应于 0 位,第二个成员对应于 1 位,如此等等。数值 SET 值 0 对应于空串。SET 成员以位值保存。每个字节的 8 个集合值可按此方式存放,因此 SET 列的存储大小是由集合成员的数目决定的,最多 64 个成员。对于大小为 1 到 8、9 到 16、17 到 24、25 到 32、33 到 64 个成员的集合,其 SET 值分别占用 1、2、3、4 或 8 个字节。
例如,还是上面的例子,我们从一个表中检索出ENUM和SET列的值,及其对应的数值:
对于ENUM类型的color列
SELECT color,color+0 from my_table
其结果为:
+--------+---------+
| color | color+0 |
+--------+---------+
| NULL | NULL |
| black | 2 |
| green | 3 |
| yellow | 4 |
| red | 1 |
| red | 1 |
| green | 3 |
| green | 3 |
| yellow | 4 |
+--------+---------+
对于SET类型的property列,同样的
SELECT property,property+0 FROM my_table;
其结果为
+-----------------+------------+
| property | property+0 |
+-----------------+------------+
| | 0 |
| house,stock | 6 |
| car,stock | 5 |
| stock | 4 |
| car,house,stock | 7 |
| car,house | 3 |
| house | 2 |
| car,stock | 5 |
| house,stock | 6 |
+-----------------+------------+
你可以仔细了解它们之间的对应关系。
因此,在给列赋值、检索时,你不仅可以使用值表中的字符串,也可以使用数值来表示一个值,例如下列语句是等价的:
INSERT my_table SET property=’car,house,stock’
INSERT my_table SET property=7
对于ENUM列也同样如此:
INSERT my_table SET color=’red’;
INSERT my_table SET color=1
1.4.6总结
本节对MySQL的数据类型和列类型进行了简单的描述。这一部分是我们继续学习SQL语言的基础,但是如果你作为一个初学者可能无法立刻理解本节的内容,没有关系,你完全可以略过,继续下去,相信在读完本书的后几章之后,在返回来,就会容易理解了。
本节中出现大量的SQL语句,尤其是建表的语句。你可能现在还不知道如何完成这些查询,没有关系,你只需要理解其中的含义就可以了。阅读了以后的几章,你就会理解这一切。
第二章 MySQL的安装
本章要点:
v MySQL的安装布局
v 如何安装MySQL
v 如何为MySQL服务器设定参数
v 如何为一个MySQL安装升级
本章介绍MySQL安装和升级的知识。由于MySQL可以在多种平台上使用,并且即使在同一平台上,也存在多种不同的安装分发,因此,MySQL的安装存在多种方法供你选择。
相对于其它的多数关系数据库系统,MySQL的安装并不复杂。本章将各种安装的说明详细记载一起,会为你安装系统提供方便。当然,还是建议你仔细阅读安装包中的说明,因为对于不同版本安装可能有的特殊性,本章无法兼顾和预期。另外,安装包中的文档相对也详尽。
MySQL在Linux上最为常用。Linux上提供各种RPM文件,可以非常方便的安装MySQL数据库系统。如果你喜欢编译源代码或者RPM分发无法在你的平台使用,你可以使用源代码安装,或者还有二进制分发可以采用。
2.1 MySQL系统的安装布局
在说明如何安装MySQL数据库系统之前,读者有必要首先了解一下MySQL的安装布局,这样才能有的放矢,更容易理解后面的叙述。这节描述安装二进制代码和源代码分发时创建的缺省目录布局。
2.1.1 二进制安装
二进制分发通过在你选择的安装地点(典型的“/usr/local/mysql”)解压缩来安装,并且在该处创建下列目录:
表2-1 二进制分发的安装布局
|
目录 |
目录的内容 |
|
Bin |
客户程序和mysqld服务器 |
|
Data |
日志文件, 数据库 |
|
include |
包含(头)文件 |
|
Lib |
库文件 |
|
scripts |
mysql_install_db |
|
share/mysql |
错误消息文件 |
|
sql-bench |
基准程序 |
2.1.2 RPM安装
rpm安装本质上也属于二进制分发,因此安装布局同上。不同之处在于它将自动安装启动脚本到/etc/rc.local目录中,并且缺省时,MySQL随系统的启动而自动启动,安装十分方便。
对于RPM分发程序、库文件、头文件和配置文件,分别安装Red Hat Linu标准的目录/usr/bin、/usr/lib/mysql、/usr/include/mysql和/etc/mysql等处。
需要特别注意的是数据库目录的位置,缺省时,/var/lib/mysql
2.1.3 源代码安装
源代码分发在你配置并编译后进行安装。缺省地,安装步骤将文件安装在“/usr/local”下的下列子目录:
表2-2 二源代码分发的安装布局
|
目录 |
目录的内容 |
|
bin |
客户程序和脚本 |
|
include/mysql |
包含(头)文件 |
|
Info |
Info格式的文档 |
|
lib/mysql |
库文件 |
|
libexec |
mysqld服务器 |
|
share/mysql |
错误消息文件 |
|
sql-bench |
基准程序和crash-me测试 |
|
var |
数据库和日志文件 |
在一个安装目录内,源代码安装的布局在下列方面不同于二进制安装:
l mysqld服务器被安装在“libexec”目录而不是“bin”目录内。
l 数据目录是“var”而非“data”。
l mysql_install_db被安装在“/usr/local/bin”目录而非“/usr/local/mysql/scripts”内。
l 头文件和库目录是“include/mysql”和“lib/mysql”而非“include”和“lib”。
2.1.4总结
本节介绍了MySQL系统的安装布局,对于源代码分发、二进制分发和RPM分发都做了阐述。阅读本章,有利于你对MySQL有一个清楚的概念,在下几节中,对于诸多繁琐的安装过程,就不再详述安装布局的内容,而是直接使用,读者应该不会感到突兀。
2.2 安装MySQL系统的分发
MyS QL是一个复杂的系统,因此相对于其它普通软件的安装,其过程要复杂、困难一些,本节将指导您完成这一过程。
2.2.1 在Windows下的安装一个二进制分装
在windows下安装一个MySQL的二进制分发十分的容易。首先你必须通过前文所述的方法获得相应的软件包,其文件名应该类似于mysql-x.xx.xx-beta-win.zip或者mysql-x.xx.xx-win.zip。如果你下载的是共享版本,应该类似于mysq-shareware-x.xx.xx-win.zip。由于MySQL的windows版本必修付费使用,共享版本有少许功能限制,因此如果只是用来学习数据库的使用,建议安装测试版本。
安装MySQL首先在某个空目录解压缩安装文件,并且运行Setup.exe程序。
缺省地,MySQL-Win32被配置安装在“C:\mysql”。如果你想要在其它地方安装MySQL,在“C:\mysql”安装它,然后将安装移到你想要的地方。或者你也可以在安装时选择其它目录。如果你真的移走MySQL,你可能需要通过提供选项给mysqld告诉mysqld需要的参数信息,尤其是数据库目录的位置。
使用C:\mysql\bin\mysqld --help显示所有的参数选项的信息。例如,如果你移动MySQL分发到“D:\programs\mysql”,你可以用D:\programs\mysql\bin\mysqld --basedir D:\programs\mysql来启动mysqld。当然有时你不必这么做,服务器也可以正常运作,不过这是一个保险的方法。
用登记的MySQL版本,你也可以创建一个“C:\my.cnf”文件来保存用于MySQL服务器的任何缺省选项。拷贝文件“\mysql\my-example.cnf”到“C:\my.cnf”并且编辑它来适用于你的安装。注意你应该用"/"而不是"\"指定所有的路径。如果你使用“\”,你需要指定两次(“\\”),因为在MySQL中“\”是转义字符。
2.2.2 在Windows NT/2000下安装成系统服务
1、安装成系统服务的方法
对于NT,比较方便的方法是把MySQL安装成NT系统服务。如上小节的方法安装完毕后,为了以系统服务的方式服务器的名字是mysqld-nt:
C:\mysql\bin\mysqld-nt --install
你可以在 NT 上使用mysqld或mysqld-opt服务器,但是那些不能作为一种系统服务启动或使用命名管道。
你可以用下列命令启动和停止MySQL服务:
c:\>net start mysql
c:\>net stop mysql
2、安装选项文件
注意,如果你按照前述方法把MySQL安装成系统服务,在这种情况下,你不能对mysqld-nt使用任何其他选项! 所以如果MySQL没有安装在缺省的位置,那么MySQL不能正确定位数据库目录,将无法启动。
作为一个变通的办法,创建一个“C:\my.cnf”文件来保存用于MySQL服务器的任何缺省选项。拷贝文件“\mysql\my-example.cnf”到“C:\my.cnf”并且编辑它来适用于你的安装。无论什么情况都建议你安装这个选项文件。你需要注意的内容是basedir,作为一个非标准安装,这是必须提供的参数:
[mysqld]
basedir = x:/path/to/mysql/
注意你应该用"/"而不是"\"指定所有的路径。如果你使用“\”,你需要指定两次(“\\”),因为在MySQL中“\”是转义字符。
3、为服务器制定参数
当你独立使用mysqld守护程序时,你可以提供参数,例如,指定一个独立的数据库目录:
c:\mysql\bin>mysqld –datadir=”d:\data\”
如果你把MySQL安装成系统服务,那么你只能在全局选项文件c:\my.cnf中为服务器提供参数。
例如这样
[mysqld]
option1
option2=value
这样相当于用如下参数启动服务器:
c:\mysql\bin>mysqld –option1 –option2=value
4、可能出现的问题
服务用MySql名字被安装,一旦安装,它必须使用服务控制管理器(SCM)实用程序启动服务(在控制面板中的管理工具中找到)或使用NET START MySQL命令。如果需要任何选项,在你启动MySQL服务前必须作为SCM实用程序的“启动参数”指定它们。一旦运行,可使用mysqladmin或从SCM实用程序或使用命令NET STOP MySQL停止mysqld-nt。如果你使用SCM停止mysqld-nt,SCM有一条关于mysqld shutdown normally奇怪的消息,当作为一种服务运行时,mysqld-nt没有控制台的存取权限,所以没有消息可以看见。
在NT上你可以得到下列服务错误消息:
Permission Denied (权限拒绝) 意味着它不能找到mysqld-nt.exe
Cannot Register (不能登记) 意味着路径是不正确的
如果你作为一种服务安装mysqld-nt有问题,尝试用完整的路径启动它:
C:\mysql\bin\mysqld --install
如果你不想作为一种服务启动mysqld-nt,你可以如下启动它:
C:\mysql\bin\mysqld-nt --standalone
或C:\mysql\bin\mysqld-nt --standalone --debug
最新的版本在“C:\mysqld.trace”给你一个调试踪迹。
2.2.3 在Linux下安装一个RPM分发
在写这个部分的时候,我假设你已经对以下提及的有基本认识并拥有相应的环境:
l 懂基本的Unix命令、基本的HTML语言和SQL
l 一个工作正常TCP/IP网络
l 一个工作正常的Linux系统(将作为你安装软件的环境)
l 在Linux环境下编译程序所必须的一些软件包,名字应该类似于:
MySQL-3.22.21-1.i386.rpm中包含了用于i386机器的服务器程序。
MySQL-client-3.22.21-1.i386.rpm包含了用于i386机器的客户端程序。
MySQL-devel-3.22.21-1.i386.rpm包含了用于在i386机器上进行开发用的包含文件和库文件(一般也可以不安装)。
l 系统没有安装MySQL
在Linux下安装一个MySQL分发也不象想象的那么困难,因为现在大多数的发行版都将MySQL打包成rpm并且集成到系统中。如果在安装系统时没有安装MySQL,你必须成为root用户才能使用rpm安装程序,以下是安装过程:
$mount /dev/cdrom /mnt/cdrom
$cd /mnt/cdrom/Redhat/RPMS
$rpm –ihv MySQL*.rpm
rpm包的安装比较简单,因为所有的事情,Red Hat Linux都为你做好了,甚至包括如何启动,以及运行服务器的用户(该方法只在Red Hat Linux系统及其兼容的系统上测试成功,应该试用大多数支持rpm系统的Linux发行版)。
2.2.4 在Linux下安装二进制分发
相对于用RPM安装来讲,用二进制安装是稍微繁琐了点。但是我们可以在安装脚本中可以自定义安装的相关参数,而不用象rpm方式只能安装默认的来安装,具有更大的自由性。
1、安装二进制分发包
如果你下载的是二进制代码,它的名字类似于: mysql-3.22.21-pc-linux-gnu-i686.tar.gz。你必须成为root用户,然后解压到 /usr/local目录,操作步骤如下:
$ cd /usr/local
$ su
# tar -zxvf /tmp/mysql-3.22.21-pc-linux-gnu-i686.tar.gz
2、建立符号链接
在所有文件解压完后,一个名字叫mysql-3.22.21-pc-linux-gnu-i686的目录将被创建出来。我们为这个目录做个符号链接,并给它一个更友好的名字mysql (免得叫mysql-3.22.21-pc-linux-gnu-i686这么长):
# ln -s mysql-3.22.21-pc-linux-gnu-i686 mysql
如果以后有新版本的MySQL的话,你可以仅仅将源码解压到新的路径,然后只需要做个符号链接就可以了。这样非常方便,数据也更加安全。
2.2.5 在Linux下安装源代码分发
挑选一个你要在其下面解包分发的目录,并且进入该目录,这里假设为/tmp。获得MySQL一个分发文件。MySQL源代码分发以压缩的tar档案提供,并且有类似于“mysql-VERSION.tar.gz”的名字,这里的VERSION是一个类似3.23.7-alpha的数字。
1、在当前目录下解包分发:
# gunzip < mysql-VERSION.tar.gz | tar xvf –
or # tar zxvf < mysql-VERSION.tar.gz
这个命令创建名为“mysql-VERSION”的一个目录。
2、进入解包分发的顶级目录:
#cd mysql-VERSION
3、设置发行版本并且编译:
#./configure--prefix=/usr/local/mysql
#make
当你运行configure时,你可能想要指定一些选项,运行./configure --help得到一张选项表。如果configure失败,你将发送包含你认为能帮你解决该问题的“config.log”的邮件,如果configure异常退出,也要包括configure的最后几行输出。用mysqlbug脚本邮寄错误报告。
4、安装所有东西:
#make install
你可能需要root用户来运行这个命令。
2.2.6 总结
本节讲述MySQL安装过程的最初部分,只有你看完下面的各节,MySQL你才能了解MySQL的完整安装过程。对于Windows平台上的安装以及Linux上的RPM安装则比较特殊,本节之后就可以使用了。
源代码安装虽然麻烦,带可以提供更大的自由性和定制性,从而使你的数据库系统更具安全性。对于不被二进制分发或者RPM分发支持的平台,使用源代码安装是唯一的途径。
2.3 安装后期的的设置与测试
本节内容主要适用与在Unix系统上,所有内容都在Red Hat Linux系统上验证通过,应该也是用于其他Linux发行版。但是对于MySQL用户权限和密码等的安全问题,Windows平台上的分发,本节的有关说明也是适用的。对于Red Hat Linux平台上的RPM分发,这些过程已经由系统完成,你也只需注意MySQL的用户安全问题。
2.3.1建立启动MySQL的帐户
为了安全性,你应该避免使用root帐户启动MySQL守护程序,创建一个专门用于启动守护程序的帐户mysql,并且让数据库属于这个帐户。
1、建立帐户mysql
#adduser mysql
2、改变数据库目录的所有者
让我们将MySQL目录和文件的拥有权改成 mysql 用户和root组:
l 对于二进制分发的安装,根据前文所述的安装方法(以缺省位置为例):
# cd /usr/local
# chown -R mysql:root mysql mysql-3.22.21-pc-linux-gnu-i686
l 对于源码安装(以缺省位置为例):
# cd /usr/local
# chown -R mysql:root var
l 对于rpm包的安装,由于实现已经全部做好,就不必处理了。
3、修改mysql.server脚本或者全局选项文件,使守护程序以规定的用户运行
改变mysql.server脚本:(mysql.server可在MySQL安装目录下的“share/mysql”目录里找到,或在MySQL源代码树的“support-files”目录下找到。)
找到行mysql_daemon_user=root,把root改为你设定的用户mysql
或者修改选项文件/etc/my.cnf:
增加选项下述选项
[mysql.server]
user=mysql #add this line
basedir=/usr/local/mysql
2.3.2 初始化授权表
一旦你已经安装了MySQL(从一个二进制代码或源代码分发),你需要初始化授权表,因为此时MySQL权限系统需要的数据库和表并不存在。然后再,启动服务器并且保证服务器正确运行。你也可以希望安排服务器在你的系统开机和关机时自动地被启动和停止。
安装授权表之前,首先请切换到mysql帐户,这也是我们很少使用这一前面建立的帐户的机会。
l 通常,对从源代码分发的安装,你象这样安装授权表并启动服务器:
#su mysql
$cd BASEDIR(缺省为/usr/local/mysql)
$./scripts/mysql_install_db
l 对二进制分发,这样做:
#su mysql
$cd BASEDIR(缺省为/usr/local/mysql)
$./bin/mysql_install_db
l 对于rpm分发,这样做:
#su mysql
$mysql_install_db
对于Win32平台上的分发,由于安装后,授权表已经存在,故没有必要使用mysql_install_db,而且也不存在这个脚本。如果你需要初始化授权表,你可以删除数据库目录中的mysql目录,即删除mysql数据库,然后再运行setup.exe文件,即可初始化授权表。
典型地,mysql_install_db仅在你第一次安装MySQL时需要运行,因此,如果你正在升级现有的安装,你可以跳过这一步。(然而,mysql_install_db的使用相当安全,并且将不更新已经存在的任何表,因此如果你是不能肯定做什么,你总是可以运行mysql_install_db。) mysql_install_db在mysql数据库里创建6个表(user、db、host、tables_priv、columns_priv和func),初始权限的描述在第七章数据库安全中给出。简单地说,这些权限允许MySQL root用户做任何事情,并且允许任何人创建立或使用一个名字以\'test\'或\'test_\'开始的数据库。
如果你不设置权限表,当你启动服务器时,下列错误将在日志文件出现:
mysqld: Can\'t find file: \'host.frm\'
2.3.3 测试服务器是否工作
1、象这样启动MySQL服务器
对于Unix下的分发 ,首先切换到mysql用户,否则如果第一次启动服务器是使用的是其他用户,那么收据库文件就为这个用户所有,之后再由用户mysql启动守护程序,就会因为数据库文件权限的问题得到一个错误。
当数据库安装完毕时,我们利用mysql.server脚本,将不必每次启动前切换到mysql用户。如果你再选项文件中指定的合适的选项,也可以不比切换到mysql用户。这一点,将在不久之后提到。
l 在Unix平台
$su mysql
$cd MYSQLD_DIR
$bin/safe_mysqld &
l 对于Win32平台的分发
c:\>cd MYSQLD_DIR
c:\>bin\mysqld –standalone
如果你安装成系统服务,也可以这样:
c:\>net start mysql
MYSQLD_DIR的值,在二进制分发中缺省为/usr/local/mysql,在源代码分发中缺省为/usr/local/libexec
2、使用mysqladmin证实服务器正在运行。
下列命令提供简单的测试来检查服务器启动和连接的应答:
$mysqladmin version
$mysqladmin variables
从mysqladmin version的输出根据你的平台和MySQL版本略有不同,但是应该类似如下显示:
$mysqladmin version
mysqladmin Ver 6.3 Distrib 3.22.9-beta, for pc-linux-gnu on i686
TCX Datakonsult AB, by Monty
Server version 3.22.9-beta
Protocol version 10
Connection Localhost via UNIX socket
TCP port 3306
UNIX socket /tmp/mysql.sock
Uptime: 16 sec
Running threads: 1 Questions: 20 Reloads: 2 Open tables: 3
为了能感受到,你能用mysqladmin做其他事情,用--help选项调用它,查看输出的帮助。
3、测试客户端连接
运行客户端程序:
# mysql
然后你可以看到屏幕显示出以下信息:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2 to server version: 3.22.21
Type \'help\' for help.
mysql>
接着,用show databases命令可以将安装的数据库列出来:
mysql> show databases;
你就可以看到:
+----------+
| Database |
+----------+
| mysql |
| test |
+----------+
2 rows in set (0.00 sec)
如果一切正常的话,那说明MySQL可以完全工作了!恭喜你!如果要退出程序,输入exit,显示结果应该类似于:
mysql> exit;
Bye
2.3.4 自动运行和停止MySQL
如果安装一个实用的数据库系统,那么让每次系统重新启动时数据库服务器自动运行是一个好主意。
一、我们现在可以由两种方法启动数据库:
1、 可以用safe_mysqld脚本来启动数据库:
$ safe_mysqld &
safe_mysqld脚本安装在MySQL安装目录的bin目录下,或可在MySQL源代码分发的scripts目录下找到。
2、mysql.server脚本可以被用来启动或停止服务器,通过用start或stop参数调用它:
$ mysql.server start
$mysql.server stop
mysql.server stop通过向服务器发出一个信号停止它。你可手工执行mysqladmin shutdown关闭服务器。
mysql.server可在MySQL二进制分发安装目录下的“share/mysql”目录里找到,或在MySQL源代码树的“support-files”目录下找到。
二、让服务器以指定的Unix用户执行
方法一:修改mysql.server脚本
当然,这样只对使用mysql.server脚本启动系统的方法其作用。
在mysql.server启动服务器之前,它把目录改变到MySQL安装目录,然后调用safe_mysqld。如果你有在一个非标准的地点安装的二进制分发,你可能需要编辑mysql.server。修改它,运行safe_mysqld前,cd到正确的目录。如果你想要作为一些特定的用户运行服务器,你可以改变mysql_daemon_user=root行使用其他用户,你也能修改mysql.server把其他选项传给safe_mysqld。
方法二:使用选项文件
通过使用选项文件,你也可以也可以避免修改mysql.server脚本。使用选项文件也可以使safe_mysqld脚本通过特定用户启动mysqld守护程序。
你也可以在一个全局“/etc/my.cnf”文件中增加mysql.server的选项。一个典型的“/etc/my.cnf”文件的一部分可能看起来像这样:
[mysql.server]
user=mysql
basedir=/usr/local/mysql
mysql.server脚本使用下列变量:user、datadir、basedir、bindir和pid-file。
当然这样只对mysql.server脚本起作用,可以把user选项加到[mysqld]段中,由于这两个脚本都调用mysqld守护程序,因此,这样可以从特定用户启动。
[mysqld]
user=mysql
basedir=/usr/local/mysql
mysqld守护程序接受的选项可以由命令mysqld –help查看。
说明,修改了mysql.server脚本或者选项文件后,你可能注意到我们没有提供用户的密码,所以如果你做了如上的修改,那么就不可以从普通帐户启动服务器,因为只有root用户才有切换到任意用户的权力。
三、让MySQL随系统启动而自动启动
当你开始使用MySQL作为生产应用时,你可能想要增加这些启动并且停止命令到在你的“/etc/rc * 文件中适当的地方。注意如果你修改mysql.server,那么如果某个时候你升级MySQL时,你的修改版本将被覆盖,因此你应该做一个你可重新安装的编辑过的版本的拷贝。
下面简述一下在Red Hat Linux系统中的设置方法:
1、修改mysql.server,把它复制到/etc/rc.d/init.d目录里面:
# cd /etc/rc.d/init.d
# cp /usr/local/mysql/support-files/mysql.server mysql
2、接着把它的属性改为“x”(executable,可执行)
# chmod +x mysql
3、最后,运行chkconfig把MySQL添加到你系统的启动服务组里面去。
# /sbin/chkconfig --del mysql
# /sbin/chkconfig --add mysql
说明
如果你的系统使用“/etc/rc.local”启动外部脚本,你也可以添加下列到其中:
二进制分发:
/bin/sh -c \'cd /usr/local/mysql ; ./bin/safe_mysqld &\'
源代码分发:
/bin/sh -c \'cd /usr/local/ ; ./bin/safe_mysqld &\'
当然,作者更推荐使用mysqlv.server的方法,因为这样可以提供系统更好的整合性。
2.3.5 更改root用户的密码
初始化授权表之后,最重要的工作是更改数据库服务器root用户的密码,这对于数据库系统的安全性非常重要,因为root用户是数据库的主宰,拥有不受限制的权限,root用户的密码失窃,就意味着MySQL不再属于你了。
在一切正常后,要做的第一件事情是更改管理员的密码,初始化授权表之后,root用户是没有密码的,这对安全有毁灭性的影响。你可以运行mysqladmin (请注意,此命令不一定在你的path中,所以最好是转到此命令的目录中直接执行):
# mysqladmin -u root password ‘newpassword’
2.3.6 修改选项文件
自版本3.22 以来,MySQL 允许在一个选项文件中存储连接参数。然后在运行 mysql 时就不用重复键入这些参数了;仅当您曾经在命令行上键入过它们时可以使用。这些参数也可以为其他 MySQL 客户机所用,如为 mysqlimport 所用。这也表示在使用这些程序时,选项文件减少了键入工作。
1、选项文件的位置
l 在Unix上,MySQL从下列文件读取缺省选择:
表2-3 Unix平台MySQL选项文件的位置
|
文件名 |
用途 |
|
/etc/my.cnf |
全局选项 |
|
DATADIR/my.cnf |
服务器特定的选项目 |
|
~/.my.cnf |
用户特定的选项 |
DATADIR是MySQL的数据目录(典型地对二进制安装是“/usr/local/mysql/data”或对源代码安装是“/usr/local/var”,RPM安装为/var/mysql)。注意:这是在配置时间指定的目录,不是mysqld启动时用--datadir指定的目录!(--datadir在服务器寻找选项文件的地方无效,因为它以前寻找他们,它处理任何命令行参数。)
l MySQL在Win32上从下列文件读取缺省选项:
表2-3 Win32平台MySQL选项文件的位置
|
文件名 |
用途 |
|
windows-system-directory\my.ini |
|
|
C:\my.cnf |
全局选项 |
|
DATADIR\my.cnf |
服务器特定的选项 |
注意,在Win32上的选项文件中,你应用/而不是\指定所有的路径,如果你使用\,你需要指定两个,因为在MySQL里面\是转义字符。
2、选项文件的应用顺序
MySQL试图以上述表格所列的顺序读取选项文件。如果存在多个选项文件,在一个后面文件读取的选项优先于在先前读取的一个文件中指定的同一个选项,在命令行上指定的选项优先于在任何选项文件指定了的选项。有些选择能使用环境变量指定,在命令行或在选项文件指定的选项优先于环境变量。
3、支持选项文件的程序
下列程序支持选项文件:mysql、mysqladmin、mysqld、mysqldump、mysqlimport、mysql.server、myisamchk和myisampack。 这也意味着,在选项文件中,每个程序对应着[程序名]的部分。
你能使用选项文件指定一个程序支持的任意长的选项!用--help选项运行程序可得到的可用选项的表。
4、选项文件的格式合作用
一个选项文件可以包含下列形式的行:
#comment
注释行以“#”或“;”开始,空行被忽略。
[group]
group是你想为其设置选项的程序或组的名字。在一个组行后,任何option或set-variable行应用于命名的组,直到选择文件结束或其他组的给出。
option
这等价于在命令行上的--option。
option=value
这等价于在命令行上的--option=value。
set-variable = variable=value
这等价于在命令行上的--set-variable variable=value。该语法必须被用来设置一个mysqld变量。
client组允许你指定适用于所有MySQL客户的选项(不是mysqld)。这是理想的组来指定你用来与服务器连接的口令。(但是保证只是选项文件本身是可读的和可写的。)
注意,对域选项和值,所有头部和尾部空白自动被删除。你可以在的值串中使用转义顺序“\b”、“\t”、“\n”、“\r”、“\\”和“\s”(“\s”==空白)。
这是一个典型的全局选项文件:
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld]
port=3306
socket=/tmp/mysql.sock
set-variable = key_buffer=16M
set-variable = max_allowed_packet=1M
[mysqldump]
quick
这是典型的用户选项文件:
[client]
# The following password will be sent to all standard MySQL clients
password=my_password
[mysql]
no-auto-rehash
5、分发文件中,样品选项文件的位置
如果你有一个源代码分发,你将在“support-files”目录下找到一个名为“my-example.cnf”样品配置文件。如果你有二进制分发,在“DIR/share/mysql”目录下查找,在此DIR是MySQL安装目录的路径(一般是“/usr/local/mysql”)。你可以拷贝“my-example.cnf”到你的主目录(重新命名拷贝为“.my.cnf”)来试验。
为了告诉一个MySQL程序不读任何选项文件,在命令行上指定--no-defaults作为第一个选项。这必须是第一个选项,否则它将无效!如果你想检查使用哪个选项,你可以给出--print-defaults选项作为第一个选项。
如果你想要强制使用一个特定配置文件,你可以使用选项--defaults-file=full-path-to-default-file。如果你这样做,只有指定的文件将被读取。
开发者注意:选项文件的处理简单地通过处理所有在任何命令行前参数的匹配选项来实现(即,在适当的组里的选项),这对使用多次指定的一个选项的最后实例的程序工作的很好。如果你有这样一个处理多重指定选项但不读选项文件的旧程序, 你只需要增加2行给与它那种能力。检查任何标准的MySQL客户的源代码看怎样做。
2.3.7总结
MySQL的安装不是把程序拷贝到硬盘上就结束了,还需要考虑多方面的内容,尤其使安全性问题。本节对MySQL的后期安装过程做了详细的叙述:
l 初始化授权表
l 用特定用户启动守护程序
l 修改root用户的密码
l 让MySQL自动启动
2.4 系统的升级
因为各种各样的原因,你可能希望升级你的数据库系统。由于数据的原因,升级比新安装一个分发要来的困难的多。
2.4.1 备份数据库与其他配置文件
如果你偏执于或担心新版本,你总能重新命名的旧mysqld为类似于mysqld-\'old-version-number\'。那么如果你的新mysqld做一些意外的事情,你可以简单地关掉它并重启你的旧mysqld!
当你做一个升级时,当然你也应该备份你的旧数据库。有时有点偏执狂是好的!
你需要备份的内容有:
l 数据库目录
l 守护程序
l 配置文件,例如选项文件
2.4.2 重新安装二进制分发
如果你是严格按照前文提示的方法安装的方法安装MySQL的二进制分发,那么升级是非常容易的。甚至没有必要备份数据库,因为升级不会覆盖旧的数据
首先所作的无非是把安装过程重复一遍。
1、把分发包解压到目录/usr/local目录
2、恢复数据。旧分发的数据库目录,完全复制到新的服务器目录中。
3、重新把/usr/local/mysql链接到新的服务器目录。
4、启动测试服务器的升级。
2.4.3重新安装源代码分发
升级一个源代码分发要复杂一些。这里假定已经有一个按照
1、 移动并备份原来的安装,因为升级过程中会覆盖数据库文件和配置文件。
2、 将源代码包解压,编译,安装
#tar zxvf mysql-version.tar.gz
#cd mysql-version
#./config
#make
#make install
3、 把原来的数据库目录/usr/local/var/的内容恢复。
4、 启动测试新的安装
2.4.4 升级一个RPM分发
升级一个RPM包分发是最为简单的,原则上你不必备份什么。因为,RPM升级可以旧版本的配置文件,不兼容的文件也是换名保存,而不是简单覆盖。但是为了安全,你可能还是会小心的备份一些数据。
找到么升级的RPM包,例如MySQL-3.23-xx.i386.rpm。
和安装类似,只是使用-U选项代替-i选项:
%rpm -Uhv MySQL-3.23-xx.i386.rpm
2.4.5 检查数据库是否工作及完整
1、 如果备份了数据,可以把数据库目录完全替换掉新分发的数据库目录
2、 启动服务器
3、 使用客户机连接到数据库,检查数据是否安全迁移
4、 检查授权表是否正常
作为升级,和安装一个新的分发有一定的不同。由于已经在上次安装中完成了各种工作,因此安装后期的工作,即第三节的安装内容,可以省略。
2.4.6总结
本节对如何升级一个系统做了简单的介绍。这里只是介绍了升级的一般过程,对于一些特殊的情况,例如从3.22升级到3.23,表的格式有所变化,可能你还想转换表的格式。在这里,就不再详细叙述了。
对于不同的分发形式,升级的过程都不复杂,原则上要注意升级失败时,你可以恢复旧的系统,那么升级就不是一件危险的事情。
2.5在同一台机器上运行多个MySQL服务器
有些情况下你可能想要在同一台机器上运行多个服务器。例如,你可能想要测试一个新的MySQL版本而让你现有生产系统的设置不受到干扰,或你可能是想要为不同的客户提供独立的MySQL安装一个因特网服务供应商。同时运行多个服务器,对于升级系统有着很大的意义,因为你可以充分测试新的分发,再决定是否升级。
同时运行多个服务器最重要的工作是,让不同的服务器运行在不同的端口和套接字上。
2.5.1使用重新编译的方法
如果你想要运行多个服务器,最容易的方法是用不同的TCP/IP端口和套接字文件重新编译服务器,因此他们不是侦听同一个TCP/IP端口或套接字。
1、如何获知当前服务器使用的端口和套接字
你可以用这个命令检查由任何当前执行的MySQL所使用的套接字和端口:
shell> mysqladmin -h hostname --port=port_number variables
应该注意下面的输出内容:
+-------------------------+----------------------------------+
| Variable_name | Value |
+-------------------------+----------------------------------+
| ansi_mode | OFF |
| back_log | 50 |
| ... | ... |
| port | 3306 |
| ... | ... |
| socket | MySQL |
| ... | ... |
+-------------------------+----------------------------------+
你可以看到,缺省的情况下,端口是3306,套接字的名字是MySQL。
2、如何指定服务器参数
这里只叙述于标准安装不同之处,其余相同的部分不再重复,但是你同样需要完成。
假设一个现存服务器配置为缺省端口号和套接字文件,那么用一个这样的configure命令行设置新的服务器:
% ./configure --with-tcp-port=port_number \
--with-unix-socket=file_name \
--prefix=/usr/local/mysql-3.23.15
这里port_number和file_name应该不同于缺省端口号和套接字文件路径名,而且--prefix值应该指定一个不同于现存的MySQL安装所在的安装目录。
3、启动服务器
这时你可以直接使用safe_mysqld脚本了
%su mysql
$/path/to/safe_mysqld &
你也应该编辑你机器的初始化脚本(可能是“mysql.server”)来启动并杀死多个mysqld服务器。
2.5.2使用指定服务器参数的方法
你不必重新编译一个新MySQL服务器,只要以一个不同的端口和套接字启动即可。
例如,对于一个二进制分发,安装到一个目录后,你可以通过指定在运行时safe_mysqld使用的选项来改变端口和套接字:
# su mysql
$ /path/to/safe_mysqld --socket=file_name --port=port_number
如果你在与开启日志的另一个服务器相同的一个数据库目录下运行新服务器,你也应该用safe_mysqld的--log和--log-update选项来指定日志文件的名字,否则,两个服务器可能正在试图写入同一个日志文件。
警告:通常你决不应该有在同一个数据库中更新数据的2个服务器!如果你的OS不支持无故障(fault-free)的系统锁定,这可能导致令人惊讶的事情发生!
如果你想要为第二个服务器使用另一个数据库目录,你可以使用safe_mysqld的--datadir=path选项。
由于一般你需要再不同的数据库目录上运行服务器,因此通常最少的参数为:
# su mysql
$ /path/to/safe_mysqld --socket=file_name --port=port_number --datadir=path_name
2.5.3有关选项文件的问题
由于全局的选项文件/etc/my.cnf和用户的选项文件~/.my.cnf被多个服务器共享,因此在这两个文件中一般只保存内容被多个服务器所共享的选项。
对于个别服务器所使用的选项,请存储在服务器的选项文件中,其位置是DATADIR/my.cnf。当然你要最先在命令行中指定--datadir=DATADIR。
对于客户机连接,当你想要连接一个正在运行的使用一个不同于编译进你的客户程序中端口的MySQL服务器时,你可以使用下列方法之一:
l 以--host \'hostname\' --port=port_numer或[--host localhost] --socket=file_name启动客户。
l 在你的C或Perl程序中,当连接MySQL服务器时,你可以给出端口和套接字参数。
l 在你启动客户程序之前,设置MYSQL_UNIX_PORT和MYSQL_TCP_PORT环境变量,指向Unix套接字和TCP/IP的端口。如果你通常使用一个特定的套接字或端口,你应该将设置这些环境变量的命令放进你的“.login”文件中。见12.1 不同的 MySQL程序概述。
l 在你的主目录下的“.my.cnf”文件中指定缺省套接字和TCP/IP端口。
2.5.4 总结
本章总结了同时运行多个服务器拷贝的方法,在实际问题中,这是很有用的,不尽对于测试新的分发,同时对备份数据库,保证数据安全也有十分重要的作用。最为一个管理员,掌握这种方法是十分必要的。
思考题
1、 请亲自安装一个MySQL分发,平台和分发包可以任意选择,要严格按照本章所介绍的方法。有可能的话,尽量在Linux平台上安装一个MySQL分发,因为这是MySQL应用最广泛的场所。
2、 安装一个MySQL分发,如何初始化授权表?之后如何更改root用户密码?
3、 将已知root@localhost用户的密码(例如,上题所更改)改变,假定原来的密码为oldpass,新的密码为newpass。使用实用程序mysqladmin。
4、 假定root用户密码为newpass,如何使用root用户连接服务器,并且发布下面的查询:
SELECT User,Host FROM mysql.user
5、 如何在选项文件中设定选项,提供mysql客户程序上题命令 行的参数 。
第三章 数据库的基本操作
本章要点:
v 服务器的启动
v 客户机与服务器的连接
v 一些SQL语句的功能
v 一些专用客户机的使用
在我们阅读了前两章,了解了MySQL并且安装成功MySQL服务器之后,可以开始学习这个强大而复杂的系统。
客户机/服务器的体系结构是MySQL的特点之一,我们首先需要熟悉MySQL客户机和服务器的使用,了解客户机如何与服务器连接。
客户机使用SQL语言与MySQL服务器通信。为了与MySQL 服务器进行通信,必须熟练掌握 SQL。例如,在使用诸如 mysql 客户机这样的程序时,其功能首先是作为一种发送 SQL 语句给服务器执行的工具。而且,如果编写使用编程语言所提供的 MySQL 接口的程序时,也必须熟悉 SQL 语言,因为需要发送 SQL 语句与服务器沟通。
本章也将对大部分SQL语句作一个详细的描述。本章涉及的SQL语句多数都是和数据的存储、检索有关,其它少量的SQL语句将在其它各章陆续介绍。
3.1 MySQL的启动与终止
由于MySQL服务器具有多种安装分发,而且能够运行在多种操作平台之上,因此它的启动与停止的方法也多种多样。你可以根据实际情况使用其中的一种。在你安装、升级或者维护系统时,你可能需要多次启动和终止服务器,你需要了解启动和终止服务器的方方面面。
3.1.1 直接运行守护程序
1、你可以采用的方法
一般的,你可以有以下几种选择启动MySQL服务器,它们的功能和用法几乎是相同的,所以一起在这里介绍:
l 直接使用MySQL守护程序mysqld启动数据库系统,尤其是Win32平台上的分发,这是因为,在Win32平台上没有mysql.server等服务器脚本可用。
l 通过调用safe_mysqld脚本,它接受与mysqld相同的参数,并试图为mysqld决定正确的选项,然后选择用那些运行它。
2、脚本或者守护程序的存放位置
对于二进制分发的安装,mysqld守护程序安装在MySQL安装目录的bin目录下,或者可在MySQL源代码分发的libexec目录下找到,缺省为/usr/local/libexec/。对于rpm分发,mysqld应该位于PATH变量决定的程序搜索路径中,因此可以直接引用。
safe_mysqld仍旧是一个脚本,并且只存在于Unix平台的分发中。safe_mysqld脚本安装在MySQL安装目录的bin目录下,或可在MySQL源代码分发的scripts目录下找到。对于rpm分发,该脚本应该位于PATH变量决定的程序搜索路径中,因此可以直接引用。
3、为什么要使用safe_mysqld脚本
safe_mysqld接受和mysqld同样的参数,并试图确定服务器程序和数据库目录的位置,然后利用这些位置调用服务器。safe_mysqld将服务器的标准错误输出重定向到数据库目录中的错误文件中,并以记录的形式存在。启动服务器后,safe_mysqld还监控服务器,并在其死机时重新启动。safe_mysqld通常用于Unix的BSD风格的版本。
如果,你曾经为root或在系统启动程序中启动safe_mysqld,其错误日志将有root拥有。如果再用非特权的用户身份调用safe_mysqld,则可能引起“Access Denied”(即,“所有权被拒绝”)的错误。此时可以删除错误文件在试一次。
由于safe_mysqld脚本的功能,使用safe_mysqld脚本明显比直接启动mysqld守护程序来得有效。
4、启动服务器的完整过程
对于Unix平台上的分发,如果你以root或在系统引导期间启动sqfe_mysqld,出错日志由root拥有,这可能在你以后试图用一个非特权用户调用safe_mysqld时将导致“permission denied”(权限拒绝)错误,删除出错日志再试一下。因此建议你在启动服务器前,首先切换到一个专门的用户mysql。
具体方法如下:
l Unix平台
$ su mysql
$ safe_mysql & (或者 mysqld & ,不推荐)
l Win32平台
C: \ mysql\bin>mysqld --standalone
或者C: \ mysql\bin>mysqld-nt –standalone
如果你使用mysqld并且没有把mysql安装在标准的位置,通常需要提供—basedir选项你的数据库的安装位置。
$safe_mysqld --basedir=”/path/to/mysql” &(Unix平台)
c:\mysql\bin>mysqld --basedir=”x:/path/to/mysql” (Win32平台)
5、使用safe_mysqld脚本实现服务器的自动启动
同样你可以利用safe_mysqld和mysqld实现服务器随操作系统自动启动。对于Linux系统以及BSD风格的系统(FreeBSD,OpenBSD等)),通常在/etc目录下有几个文件在引导时初始化服务,这些文件通常有以“rc”开头的名字,且它有可能由一个名为“rc.local”的文件(或类似的东西),特意用于启动本地安装的服务。
在这样的系统上,你可能将类似于下列的行加入rc.local文件中以启动服务器(如果safe_mysqld的目录在你的系统上不同,修改它即可):
if [ -x /usr/local/bin/safe_mysqld ]; then /usr/local/bin/safe_mysqld & fi
由于这样在引导时启动,将使用root身份启动数据库,在某些时候可能会产生问题和麻烦。这是你可以指定--user选项,因此可以将上面的代码修改为:
if [ -x /usr/local/bin/safe_mysqld ]; then
/usr/local/bin/safe_mysqld --user=mysql --datadir=/path/to/data &
fi
3.1.2 使用脚本mysql.server启动关闭数据库
对于Unix平台上的分发,比较好的办法是使用数据库脚本mysql.server,启动和关闭数据库。
1、mysql.server脚本的存放位置
mysql.server脚本安装在MySQL安装目录下的share/mysqld目录下或可以在MySQL源代码分发的support_files目录下找到。对于rpm分发,该脚本已经改名mysql位于/etc/rc.d/init.d目录中,另外在….中存在一个副本mysql.server。下文的讨论对RPM分发来说,都在安装中完成了。如果你想使用它们,你需要将它们拷贝到适当的目录下。
2、如何使用mysql.server脚本启动停止服务器
mysql.server脚本可以被用来启动或停止服务器,通过用start或stop参数调用它:
$ mysql.server start
$ mysql.server stop
3、mysql.server的功能简述
在mysql.server启动服务器之前,它把目录改变到MySQL安装目录,然后调用safe_mysqld。如果你有在一个非标准的地点安装的二进制分发,你可能需要编辑mysql.server。修改它,运行safe_mysqld前,cd到正确的目录。
4、让mysql.server以特定的用户启动服务器
如果你想要作为一些特定的用户运行服务器,你可以改变mysql_daemon_user=root行使用其他用户,你也能修改mysql.server把其他选项传给safe_mysqld。
当然你也可以利用选项文件给mysql.server脚本提供参数。
你也可以在一个全局“/etc/my.cnf”文件中增加mysql.server的选项。一个典型的“/etc/my.cnf”文件可能看起来像这样:
[mysqld]
datadir=/usr/local/mysql/var
socket=/tmp/mysqld.sock
port=3306
[mysql.server]
user=mysql
basedir=/usr/local/mysql
mysql.server脚本使用下列变量:user、datadir、basedir、bindir和pid-file。
5、利用mysql.server脚本让服务器自动启动
mysql.server脚本的重要性在于你可以使用它配置一个随操作系统自动启动的数据库安装,这是一个实际的系统中常用的方法。
l 把mysql.server复制到/etc/rc.d/init.d目录里面:
# cd /etc/rc.d/init.d
# cp /usr/local/mysql/support-files/mysql.server mysql
l 接着把它的属性改为“x”(executable,可执行)
# chmod +x mysql
l 最后,运行chkconfig把MySQL添加到你系统的启动服务组里面去。
# /sbin/chkconfig --del mysql
# /sbin/chkconfig --add mysql
你也可以这样做,手工建立链接:
#cd /etc/rc.d/rc3.d (根据你的运行级不同而不同,可以是rc5.d)
#ln –s ../init.d/mysql S99mysql
在系统启动期间,S99mysql脚本利用start参数自动启动。
3.1.3 使用mysqladmin实用程序关闭、重启数据库
日常维护数据库,经常需要关闭或者重新启动数据库服务器。mysql.server stop只能用于关闭数据库系统,并不方便,而且mysql.server脚本用特定用户身份启动服务器,因此使用该教本需要超级用户的权限。相比之下mysqladmin就方便的多,并且适用于MySQL所有类型、平台的安装。
l 关闭数据库服务器
mysqladmin shutdown
l 重启数据库服务器
mysqladmin reload
l 获得帮助
mysqladmin –help
mysqladmin实用程序非常有使用价值,仔细阅读帮助输出,你会得到更多的用法。
如果出现下面的错误:
mysqladmin: connect to server at \'localhost\' failed
error: \'Access denied for user: \'root@localhost\' (Using password: YES)\'
表示你需要一个可以正常连接的用户,请指定-u -p选项,具体方法与3.2节介绍相同,在第七章中你将会学到用户授权的知识。例如,你现在可以:
shell>mysqladmin -u root -p shutdown
Enter Password:***********
输入你在阅读第二章时修改过的密码即可。
3.1.4 启动或停止NT平台上的系统服务
上面几节介绍了Unix平台上使数据库服务器自动启动的方法,而在windows(NT)平台上为了让MySQL数据库自动启动,你需要将MySQL服务器安装成NT系统的一种服务。
1、将MySQL安装成系统服务
对于NT,服务器名字是mysqld-nt。
C:\mysql\bin> mysqld-nt --install
(你可以在 NT 上使用mysqld或mysqld-opt服务器,但是那些不能作为一种服务启动或使用命名管道。)
2、修改选项文件
如果你的mysql没有安装缺省的位置c:\mysql,那么因为数据库将无法确定数据库目录的位置,而无法启动。这种情况下,你需要提供一个全局的选项文件c:\my.cnf。将安装目录中的my-example.cnf文件拷贝到c盘根目录下。修改或加入:
[mysqld]
basedir = x:/path/to/mysql/
3、启动、停止服务器的方法
你可以用下列命令启动和停止MySQL服务:
NET START mysql
NET STOP mysql
注意在这种情况下,你不能对mysqld-nt使用任何其他选项!你需要使用选项文件提供参数。可以在选项文件中提供合适的参数。
3.1.5 使用选项文件提供服务器的参数
本节介绍守护程序需要的比较重要的选项。
对于全局选项文件(windows:c:/my.cnf 或者 unix:/etc/my.cnf),比较重要的选项有:
user 运行守护程序的用户,如果你使用mysql.server,并且在[mysql.server]中指定了user,那么这个选项没有必要。
log-update=file 更新日志名,对于恢复数据库有重要意义,数据库服务器将生成file.n为名的更新日志文件。
-l, --log[=file] 指定常规日志名
--log-bin[=file] 指定使用的二进制日志文件,应用于服务器复制。
-Sg, --skip-grant-tables 启动时不加载授权表,维护时使用。
-u, --user=user_name 启动服务器使用的Unix帐户
--socket=... 指定是用的Unix套接字文件名,在同时运行多个服务器时使用。
-P, --port=... 指定服务器使用的端口,在同时运行多个服务器时使用。
3.1.6 总结
作为MySQL的管理员,你平时的指责就是确保服务器尽可能的正常运行,使得客户机能够正常访问。本章讨论了如何启动和重启、关闭服务器,如果你具备了这个能力,就可以更好的维护服务器安装。本章介绍的方法,多数适合于Unix系统,读者请仔细分辨。
3.2 MySQL与客户机的连接
本章通过演示如何使用mysql客户程序与数据库服务器连接。mysql(有时称为“终端监视器”或只是“监视”)是一个交互式程序,允许你连接一个MySQL服务器,运行查询并察看结果。mysql可以用于批模式:你预先把查询放在一个文件中,然后告诉mysql执行文件的内容。使用mysql的两个方法都在这里涉及。
为了看清由mysql提供的一个选择项目表了,用--help选项调用它:
shell> mysql --help
本章假定mysql已经被安装在你的机器上,并且有一个MySQL服务器你可以连接。如果这不是真的,联络你的MySQL管理员。(如果你是管理员,你将需要请教这本手册的其他章节。)
3.2.1建立和中止与服务器的连接
1、如何使用客户机建立连接
为了连接到服务器,从外壳程序(即从 UNIX 提示符,或从 Windows 下的 DOS 控制台)激活 mysql 程序。命令如下:
shell>mysql
又如,直接连接一个数据库:
shell> mysql db_name
其中的“$”在本书中代表外壳程序提示符。这是 UNIX 标准提示符之一;另一个为“#”。在 Windows 下,提示符类似 “c:\>”。
2、客户机最常使用的选项:主机、用户和密码
为了连接服务器,当你调用mysql时,你通常将需要提供一个MySQL用户名和很可能,一个口令。如果服务器运行在不是你登录的一台机器上,你也将需要指定主机名。联系你的管理员以找出你应该使用什么连接参数进行连接(即,那个主机,用户名字和使用的口令)。一旦你知道正确的参数,你应该能象这样连接:
shell> mysql -h host -u user -p
Enter password: ********
********代表你的口令;当mysql显示Enter password:提示时输入它。
在刚开始学习 MySQL 时,大概会为其安全系统而烦恼,因为它使您难于做自己想做的事。(您必须取得创建和访问数据库的权限,任何时候连接到数据库都必须给出自己的名字和口令。)但是,在您通过数据库录入和使用自己的记录后,看法就会马上改变了。这时您会很欣赏 MySQL 阻止了其他人窥视(或者更恶劣一些,破坏!)您的资料。
下面介绍选项的含义:
-h host_name(可选择形式:--host=host_name)
希望连接的服务器主机。如果此服务器运行在与 mysql 相同的机器上,这个选项一般可省略。
l -u user_name(可选择的形式:--user=user_name)
您的 MySQL 用户名。如果使用 UNIX 且您的 MySQL 用户名与注册名相同,则可以省去这个选项;mysql 将使用您的注册名作为您的 MySQL 名。
在 Windows 下,缺省的用户名为 ODBC。这可能不一定非常有用。可在命令行上指定一个名字,也可以通过设置 USER 变量在环境变量中设置一个缺省名。如用下列 set 命令指定 paul 的一个用户名:
l -p(可选择的形式:--password)
这个选项告诉 mysql 提示键入您的 MySQL 口令。注意:可用 -pyour_password 的形式(可选择的形式:--password=your_password)在命令行上键入您的口令。但是,出于安全的考虑,最好不要这样做。选择 -p 不跟口令告诉 mysql 在启动时提示您键入口令。例如:
在看到 Enter password: 时,键入口令即可。(口令不会显到屏幕,以免给别人看到。)请注意,MySQL 口令不一定必须与 UNIX 或 Windows 口令相同。
如果完全省略了 -p 选项,mysql 就认为您不需要口令,不作提示。
请注意:-h 和 -u 选项与跟在它们后面的词有关,无论选项和后跟的词之间是否有空格。而 -p 却不是这样,如果在命令行上给出口令,-p 和口令之间一定不加空格。
例如,假定我的 MySQL 用户名和口令分别为 tom 和 secret,希望连接到在我注册的同一机器上运行的服务器上。下面的 mysql 命令能完成这项工作:
shell>mysql –u tom -p
在我键入命令后,mysql 显示 Enter password: 提示键入口令。然后我键入口令(****** 表明我键入了 secret)。
如果一切顺利的话,mysql 显示一串消息和一个“mysql>”提示,表示它正等待我发布查询。完整的启动序列如下所示:
为了连接到在其他某个机器上运行的服务器,需要用 -h 指定主机名。如果该主机为 mysql.domain.net,则相应的命令如下所示:
shell>mysql –h mysql.domain.net –u tom -p
在后面的说明 mysql 命令行的多数例子中,为简单起见,我们打算省去 -h、-u 和 -p 选项。并且假定您将会提供任何所需的选项。
有很多设置账号的方法,从而不必在每次运行 mysql 时都在连接参数中进行键入。这个问题在前面已经介绍过,你只需在选项文件中提供参数,具体请看3.2.2。您可能会希望现在就跳到该节,以便找到一些更易于连接到服务器的办法。
3、结束会话
在建立了服务器的一个连接后,可在任何时候键入下列命令来结束会话:
quit exit
还可以键入 Control-D 来退出,至少在 UNIX 上可以这样。
3.2.2利用选项文件简化连接
在激活 mysql 时,有可能需要指定诸如主机名、用户名或口令这样的连接参数。运行一个程序需要做很多输入工作,这很快就会让人厌烦。利用选项文件可以存储连接参数,减少输入工作。
例如,对于使用mysqladmin客户机来管理数据库,那么你很快会厌烦每次使用这么长的命令行:
shell>mysql –u root –p varialbles
Enter password: *********
你也许会选择使用全局选项文件来存贮你的参数:
[mysqladmin]
#也可以用[client],为所有的客户机存储参数
user=root
password=yourpassword
这样执行mysqladmin variables就不会显示任何存储拒绝的错误,并且你可以用root用户身份维护数据库了。
且慢,你立刻会发现,这样做是一个很大的安全漏洞,因为任何可以读取选项文件的用户都可以获得你的密码!解决方法是,只提供password选项不提供密码:
[mysqladmin]
user=root
password
这样你在命令行执行时,会提示你数据密码:
shell>mysql varialbles
Enter password: *********
但是,你不能不提供password选项,否则你还是要在命令行中提供-p选项。
3.2.3 利用 mysql 的输入行编辑器
mysql 具有内建的 GNU Readline 库,允许对输入行进行编辑。可以对当前录入的行进行处理,或调出以前输入的行并重新执行它们(原样执行或做进一步的修改后执行)。在录入一行并发现错误时,这是非常方便的;您可以在按 Enter 键前,在行内退格并进行修正。如果录入了一个有错的查询,那么可以调用该查询并对其进行编辑以解决问题,然后再重新提交它。(如果您在一行上键入了整个查询,这是最容易的方法。)
表2-1中列出了一些非常有用的编辑序列,除了此表中给出的以外,还有许多输入编辑命令。利用因特网搜索引擎,应该能够找到 Readline手册的联机版本。此手册也包含在 Readline 分发包中,可在 http://www.gnu. org/ 的 Gnu Web 站点得到。
表2-1 mysql 输入编辑命令
|
键 序 列 |
说 明 |
|
Up 箭头,Ctrl-p |
调前面的行 |
|
Down 箭头,Ctrl-N |
调下一行 |
|
Left 箭头,Ctrl-B |
光标左移(向后) |
|
Right 箭头,Ctrl-F |
光标右移(向前) |
|
Escape Ctrl-B |
向后移一个词 |
|
Escape Ctrl-F |
向前移一个词 |
|
Ctrl-A |
将光标移到行头 |
|
Ctrl-E |
将光标移到行尾 |
|
Ctrl-D |
删除光标下的字符 |
|
Delete |
删除光标左边的字符 |
|
Escape D |
删词 |
|
Escape Backspace |
删除光标左边的词 |
|
Ctrl-K |
删除光标到行尾的所有字符 |
|
Ctrl-_ |
撤消最后的更改;可以重复 |
下面的例子描述了输入编辑的一个简单的使用。假定用 mysql 输入了下列查询:
如果在按 Enter 前,已经注意到将“president”错拼成了“persident”,则可按左箭头或 Ctrl-B 多次移动光标到“s”的左边。然后按 Delete 两次删除“er”,键入“re”改正错误,并按 Enter 发布此查询。如果没注意到错拼就按了 Enter,也不会有问题。在 mysql 显示了错误消息后,按上箭头或 Ctrl-P 调出该行,然后对其进行编辑。
输入行编辑在 mysql 的 Windows 版中不起作用,但是可从 MySQL Web 站点取得免费的 cygwin_32 客户机分发包。在该分发包中的mysqlc 程序与 mysql 一样,但它支持输入行编辑命令。
3.2.4 批处理模式连接
在前面的章节中,你交互式地使用mysql输入查询并且查看结果。你也可以以批模式运行mysql。为了做到这些,把你想要运行的命令放在一个文件中,然后告诉mysql从文件读取它的输入:
shell> mysql < batch-file
如果你需要在命令行上指定连接参数,命令可能看起来像这样:
shell> mysql -h host -u user -p < batch-file
Enter password: ********
当你这样使用mysql时,你正在创建一个脚本文件,然后执行脚本。
为什么要使用一个脚本?有很多原因:
l 如果你重复地运行查询(比如说,每天或每周),把它做成一个脚本使得你在每次执行它时避免重新键入。
l 你能通过拷贝并编辑脚本文件从类似的现有的查询生成一个新查询。
l 当你正在开发查询时,批模式也是很有用的,特别对多行命令或多行语句序列。如果你犯了一个错误,你不必重新打入所有一切,只要编辑你的脚本来改正错误,然后告诉mysql再次执行它。
l 如果你有一个产生很多输出的查询,你可以通过一个分页器而不是盯着它翻屏到你屏幕的顶端来运行输出:
$ mysql < batch-file | more
l 你能捕捉输出到一个文件中进行更一步的处理:
shell> mysql < batch-file > mysql.out
l 你可以散发脚本给另外的人,因此他们也能运行命令。
l 一些情况不允许交互地使用,例如, 当你从一个cron任务中运行查询时。在这种情况下,你必须使用批模式。
当你以批模式运行mysql时,比起你交互地使用它时,其缺省输出格式是不同的(更简明些)。例如,当交互式运行SELECT DISTINCT species FROM pet时,输出看起来像这样:
+---------+
| species |
+---------+
| bird |
| cat |
| dog |
| hamster |
| snake |
+---------+
但是当以批模式运行时,像这样:
species
bird
cat
dog
hamster
snake
如果你想要在批模式中得到交互的输出格式,使用mysql -t。为了回显以输出被执行的命令,使用mysql -vvv。
3.2.5 总结
本章中列举了客户机与服务器连接的几种情况,读者需要注意的是下面几点:
1、 如何提供参数,以及参数的意义
2、 如何让客户机提示输入密码
3、 交互模式和批处理模式
4、 mysql客户机的行编辑功能
3.3 有关数据库的操作
从本节开始正式介绍各种SQL语句。本节介绍有关数据库级的SQL以及相关操作,查看、建立和删除等操作。
3.3.1 用SHOW显示已有的数据库
句法:SHOW DATABASES [LIKE wild]
如果使用LIKE wild部分,wild字符串可以是一个使用SQL的“%”和“_”通配符的字符串。
功能:SHOW DATABASES列出在MySQL服务器主机上的数据库。
你可以尝试下面举例,观察输出结果,例如:
mysql>show databases;
+----------+
| Database |
+----------+
| first |
| mysql |
| mytest |
| test |
| test1 |
+----------+
mysql>show databases like ‘my%’;
+----------------+
| Database (my%) |
+----------------+
| mysql |
| mytest |
+----------------+
用mysqlshow程序也可以得到已有数据库列表。
3.3.2 用Create Dabase 创建数据库
句法:CREATE DATABASE db_name
功能:CREATE DATABASE用给定的名字创建一个数据库。
如果数据库已经存在,发生一个错误。
在MySQL中的数据库实现成包含对应数据库中表的文件的目录。因为数据库在初始创建时没有任何表,CREATE DATABASE语句只是在MySQL数据目录下面创建一个目录。
例如:
mysql>create database myfirst;
然后利用show databases观察效果。
3.3.3 用DROP DATABASE删除数据库
句法:DROP DATABASE [IF EXISTS] db_name
功能:DROP DATABASE删除数据库中的所有表和数据库。要小心地使用这个命令!
DROP DATABASE返回从数据库目录被删除的文件的数目。通常,这3倍于表的数量,因为每张表对应于一个“.MYD”文件、一个“.MYI”文件和一个“.frm”文件。
在MySQL 3.22或以后版本中,你可以使用关键词IF EXISTS阻止一个错误的发生,如果数据库不存在。
3.3.4 使用mysqladmin工具创建和删除
在命令行环境下可以使用mysqladmin创建和删除数据库。
创建数据库:
shell> mysqladmin create db_name
删除数据库:
shell> mysqladmin drop db_name
如果出现下面的错误:
mysqladmin: connect to server at \'localhost\' failed
error: \'Access denied for user: \'root@localhost\' (Using password: YES)\'
表示你需要一个可以正常连接的用户,请指定-u -p选项,具体方法与3.2节介绍相同,在第七章中你将会学到用户授权的知识。
3.3.5 直接在数据库目录中创建或删除
用上述方法创建数据库,只是MySQL数据目录下面创建一个与数据库同名目录,同样删除数据库是把这个目录删除。
所以,你可以直接这么做,创建或删除数据库,或者给数据库更名。这对备份和恢复备份有一定意义。
3.3.6 用USE选用数据库
句法:USE db_name
USE db_name语句告诉MySQL使用db_name数据库作为随后的查询的缺省数据库。数据库保持到会话结束,或发出另外一个USE语句:
mysql> USE db1;
mysql> SELECT count(*) FROM mytable; # selects from db1.mytable
mysql> USE db2;
mysql> SELECT count(*) FROM mytable; # selects from db2.mytable
如果你不是用USE语句,那么上面的例子应该写成:
mysql> SELECT count(*) FROM db1.mytable;
mysql> SELECT count(*) FROM db2.mytable;
由于use也是一个mysql客户程序的命令,所以你可以在命令行最后不加分号,客户程序可以得到结果。
3.3.7 总结
本节介绍了有关数据库操作的SQL语句、实用程序,其中包括:
l SQL语句:CREATE/DROP DATABASE,SHOW DATABASES,USE
l 程序mysqladmin
l 直接创建或删除数据库的目录
3.4 有关数据表的操作
用MySQL,目前(版本 3.23)你可以在三种基本数据库表格式间选择。当你创建一张表时,你可以告诉MySQL它应该对于表使用哪个表类型。MySQL将总是创建一个.frm文件保存表和列定义。视表类型而定,索引和数据将在其他文件中存储。
你能用ALTER TABLE语句在不同类型的表之间变换。见7.8 ALTER TABLE语法。
l MyISAM
在MySQL 3.23中,MyISAM是缺省表格类型,它是基于ISAM代码并且有很多有用的扩展。索引存储在一个有.MYI(MYindex)扩展名的文件并且数据存储在有.MYD(MYData)扩展名的文件中。你能用myisamchk实用程序检查/修复MyISAM表。
l ISAM
你也可以使用放弃的ISAM。这将在不久消失,因为MyISAM是同一个东西的更好实现。ISAM使用一个B-tree索引,这个索引存储在一个有.ISM扩展名的文件中并且数据存储在有.ISD扩展名的文件中,你可用isamchk实用程序检查/修复ISAM表。ISAM表不是跨OS/平台二进制可移植的。
l HEAP
HEAP表格使用一个杂凑(hashed)索引并且存储在内存中。这使他们更快,但是如果MySQL崩溃,你将失去所有存储的数据。HEAP作为临时表很可用!
3.4.1 用SHOW/ DESCRIBE语句显示数据表的信息
句法:
SHOW TABLES [FROM db_name] [LIKE wild]
or SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
or SHOW INDEX FROM tbl_name [FROM db_name]
or SHOW TABLE STATUS [FROM db_name] [LIKE wild]
{DESCRIBE | DESC} tbl_name {col_name | wild}
你能使用db_name.tbl_name作为tbl_name FROM db_name句法的另一种选择。
l SHOW TABLES列出在一个给定的数据库中的表。你也可以用mysqlshow db_name命令得到这张表。
注意:如果一个用户没有一个表的任何权限,表将不在SHOW TABLES或mysqlshow db_name中的输出中显示。
l SHOW COLUMNS列出在一个给定表中的列。如果列类型不同于你期望的是基于CREATE TABLE语句的那样,注意,MySQL有时改变列类型。
l DESCRIBE语句提供了类似SHOW COLUMNS的信息。DESCRIBE提供关于一张表的列的信息。col_name可以是一个列名字或包含SQL的“%”和“_”通配符的一个字符串。这个语句为了与 Oracle 兼容而提供的。
l SHOW TABLE STATUS(在版本3.23引入)运行类似SHOW STATUS,但是提供每个表的更多信息。你也可以使用mysqlshow --status db_name命令得到这张表。
l SHOW FIELDS是SHOW COLUMNS一个同义词,SHOW KEYS是SHOW INDEX一个同义词。
l 你也可以用mysqlshow db_name tbl_name或mysqlshow -k db_name tbl_name 列
出一张表的列或索引。
l SHOW INDEX以非常相似于ODBC的SQLStatistics调用的格式返回索引信息。
3.4.2 使用mysqlshow 工具得到信息
下面简单介绍一下mysqlshow实用程序的用法,在得到数据库和表的信息上,使用起来非常方便。
得到已有数据库的列表:
shell> mysqlshow
列出某数据库db_name中已有的表:
shell> mysqlshow db_name
列出某数据库表db_name.tbl_name的结构信息:
shell>mysqlshow db_name tbl_name
列出一张表的索引:
shell> mysqlshow –k db_name tbl_name
3.4.3 用Create Table 语句创建数据表
用 CREATE TABLE 语句创建表。此语句的完整语法是相当复杂的,因为存在那么多的可选子句,但在实际中此语句的应用相当简单。如我们在第 1 章中使用的所有 CREATE TABLE 语句都不那么复杂。
有意思的是,大多数复杂东西都是一些子句,这些子句MySQL在分析后扔掉。参阅附录 1 可以看到这些复杂的东西。
1、CREATE TABLE 语句的基本语法
CREATE TABLE tbl_name(create_definition,...) [TYPE =table_type]
create_definition: col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT][PRIMARY KEY]
在MySQL3.22或以后版本中,表名可以被指定为db_name.tbl_name,不管有没有当前的数据库都可以。
例如,创建一个访问者留言表:
shell> mysql –u root –p
mysql> create database mytest;
mysql> CREATE TABLE guestbook
-> (
-> visitor VARCHAR(40),
-> comments TEXT,
-> entrydate DATETIME
->);
如果一切正常,祝贺你,你已经建立了你的第一个表!
你所创建的表名为guestbook,你可以使用这个表来存储来字你站点访问者的信息。你是用REEATE TABLE语句创建的这个表,这个语句有两部分:第一部份指定表的名子;第二部份是括在括号中的各字段的名称和属性,相互之间用逗号隔开。
表guestbook有三个字段:visitor,comments 和entrydate。visitor字段存储访问者的名字,comments字段存储访问者对你站点的意见,entrydate字段存储访问者访问你站点的日期和时间。
注意每个字段名后面都跟有一个专门的表达式。例如,字段名comments后面跟有表达式TEXT。这个表达式指定了字段的数据类型。数据类型决定了一个字段可以存储什么样的数据。因为字段comments包含文本信息,其数据类型定义为文本型。
2、如何指定表的类型
你也可以在创建表时指定表的类型,如果不指定表的类型,在3.22及以前版本中缺省为ISAM表,在3.23版本中缺省为MyISAM表。你应该尽量使用MyISAM表。指定表的类型经常用于创建一个HEAP表:
mysql> CREATE TABLE fast(id int,articles TEXT) TYPE=HEAP;
3、隐含的列说明的改变
在某些情况下,MySQL隐含地改变在一个CREATE TABLE语句给出的一个列说明。(这也可能在ALTER TABLE。)
l 长度小于4的VARCHAR被改变为CHAR。
l 如果在一个表中的任何列有可变长度,结果是整个行是变长的。因此, 如果一张表包含任何变长的列(VARCHAR、TEXT或BLOB),所有大于3个字符的CHAR列被改变为VARCHAR列。这在任何方面都不影响你如何使用列;在MySQL中,VARCHAR只是存储字符的一个不同方法。MySQL实施这种改变,是因为它节省空间并且使表操作更快捷。
l TIMESTAMP的显示尺寸必须是偶数且在2 ~ 14的范围内。如果你指定0显示尺寸或比14大,尺寸被强制为14。从1~13范围内的奇数值尺寸被强制为下一个更大的偶数。
l 你不能在一个TIMESTAMP列里面存储一个文字NULL;将它设为NULL将设置为当前的日期和时间。因为TIMESTAMP列表现就是这样,NULL和NOT NULL属性不以一般的方式运用并且如果你指定他们,将被忽略。DESCRIBE tbl_name总是报告该TIMESTAMP列可能赋予了NULL值。
如果你想要知道MySQL是否使用了除你指定的以外的一种列类型,在创建或改变你的表之后,发出一个DESCRIBE tbl_name语句即可。
3.4.4利用 SELECT 的结果创建表
关系数据库的一个重要概念是,任何数据都表示为行和列组成的表,而每条 SELECT 语句的结果也都是一个行和列组成的表。在许多情况下,来自 SELECT 的“表”仅是一个随着您的工作在显示屏上滚动的行和列的图像。在 MySQL 3.23 以前,如果想将 SELECT 的结果保存在一个表中以便以后的查询使用,必须进行特殊的安排:
1) 运行 DESCRIBE 或 SHOW COLUMNS 查询以确定想从中获取信息的表中的列类型。
2) 创建一个表,明确地指定刚才查看到的列的名称和类型。
3) 在创建了该表后,发布一条 INSERT ... SELECT 查询,检索出结果并将它们插入所创建的表中。
在 MySQL 3.23 中,全都作了改动。CREATE TABLE ... SELECT 语句消除了这些浪费时间的东西,使得能利用 SELECT 查询的结果直接得出一个新表。只需一步就可以完成任务,不必知道或指定所检索的列的数据类型。这使得很容易创建一个完全用所喜欢的数据填充的表,并且为进一步查询作了准备。
l 如果你在CREATE语句后指定一个SELECT,MySQL将为在SELECT中所有的单元创键新字段。例如:
mysql> CREATE TABLE test
-> (a int not null auto_increment,primary key (a), key(b))
-> SELECT b,c from test2;
这将创建一个有3个列(a,b,c)的表,其中b,c列的数据来自表test2。注意如果在拷贝数据进表时发生任何错误,表将自动被删除。
l 可以通过选择一个表的全部内容(无 WHERE 子句)来拷贝一个表,或利用一个总是失败的 WHERE 子句来创建一个空表,如:
mysql> CREATE TABLE test SELECT * from test2;
mysql> CREATE TABLE test SELECT * from test2 where 0;
如果希望利用 LOAD DATA 将一个数据文件装入原来的文件中,而不敢肯定是否具有指定的正确数据格式时,创建空拷贝很有用。您并不希望在第一次未得到正确的选项时以原来表中畸形的记录而告终。利用原表的空拷贝允许对特定的列和行分隔符用 LOAD DATA 的选项进行试验,直到对输入数据的解释满意时为止。在满意之后,就可以将数据装入原表了。
可结合使用 CREATE TEMPORARY TABLE 与 SELECT 来创建一个临时表作为它自身的拷贝,如:
这允许修改 my_tbl 的内容而不影响原来的内容。在希望试验对某些修改表内容的查询,而又不想更改原表内容时,这样做很有用。为了使用利用原表名的预先编写的脚本,不需要为引用不同的表而编辑这些脚本;只需在脚本的起始处增加 CREATE TEMPORARY TABLE 语句即可。相应的脚本将创建一个临时拷贝,并对此拷贝进行操作,当脚本结束时服务器会自动删除这个拷贝。
要创建一个作为自身的空拷贝的表,可以与 CREATE TEMPORARY ... SELECT 一起使用 WHERE 0 子句,例如:
但创建空表时有几点要注意。在创建一个通过选择数据填充的表时,其列名来自所选择的列名。如果某个列作为表达式的结果计算,则该列的“名称”为表达式的文本。表达式不是合法的列名,可在 mysql 中运行下列查询了解这一点:
为了正常工作,可为该列提供一个合法的别称:
如果选择了来自不同表的具有相同名称的列,将会出现一定的困难。假定表 t1 和 t2 两者都具有列 c,而您希望创建一个来自两个表中行的所有组合的表。那么可以提供别名指定新表中惟一性的列名,如:
通过选择数据进行填充来创建一个表并会自动拷贝原表的索引。
3.4.5 用Alter Table语句修改表的结构
有时你可能需要改变一下现有表的结构,那么Alter Table语句将是你的合适选择。
l 增加列
alter table tbl_name add col_name type
例如,给表增加一列weight
mysql>alter table pet add weight int;
l 删除列
alter table tbl_name drop col_name
例如,删除列weight:
mysql>alter table pet drop weight;
l 改变列
alter table tbl_name modify col_name type
例如,改变weight的类型:
mysql> alter table pet modify weight samllint;
另一种方法是:
alter table tbl_name change old_col_name col_name type
例如:
mysql> alter table pet change weight weight samllint;
l 给列更名
mysql>alter table pet change weight wei;
l 给表更名
alter table tbl_name rename new_tbl
例如,把pet表更名为animal
mysql>alter table pet rename animal;
l 改变表的类型
另外,可以为列增加或删除索引等属性,不再详述,请参阅附录。
3.4.6 用DROP Table 语句删除数据表
DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]
DROP TABLE删除一个或多个数据库表。所有表中的数据和表定义均被删除,故小心使用这个命令!
在MySQL 3.22或以后版本,你可以使用关键词IF EXISTS类避免不存在表的一个错误发生。
例如:
mysql>use mytest;
mysql>drop table guestbook;
或者,也可以同时指定数据库和表:
mysql>drop table mytest. guestbook;
3.4.7 总结
本节讲述了有关表的大部分操作,现在将所述内容总结如下:
l MySQL的表的三种类型
l 如何创建表、删除表
l 如何改变表的结构、名字
l 如何使用mysqlshow实用程序
3.5 向数据表插入行记录
3.5.1 使用insert语句插入新数据
语法:INSERT [INTO] tbl_name [(col_name,...)] VALUES (pression,...),…
INSERT [INTO] tbl_name SET col_name=expression, ...
让我们开始利用 INSERT 语句来增加记录,这是一个 SQL 语句,需要为它指定希望插入数据行的表或将值按行放入的表。INSERT 语句具有几种形式:
l 可指定所有列的值:
例如:
shell> mysql –u root –p
mysql> use mytest;
mysql> insert into worker values(“tom”,”tom@yahoo.com”);
“INTO”一词自 MySQL 3.22.5 以来是可选的。(这一点对其他形式的 INSERT 语句也成立。)VALUES 表必须包含表中每列的值,并且按表中列的存放次序给出。(一般,这就是创建表时列的定义次序。如果不能肯定的话,可使用 DESCRIBE tbl_name 来查看这个次序。)
l 使用多个值表,可以一次提供多行数据。
Mysql>insert into worker values(‘tom’,’tom@yahoo.com’),(‘paul’,’paul@yahoo.com’);
有多个值表的INSERT ... VALUES的形式在MySQL 3.22.5或以后版本中支持。
l 可以给出要赋值的那个列,然后再列出值。这对于希望建立只有几个列需要初始设置的记录是很有用的。
例如:
mysql>insert into worker (name) values (‘tom’);
自 MySQL 3.22.5 以来,这种形式的 INSERT 也允许多个值表:
mysql>insert into worker (name) values (‘tom’), (‘paul’);
在列的列表中未给出名称的列都将赋予缺省值。
自 MySQL 3.22 .10 以来,可以 col_name = value 的形式给出列和值。
例如:
mysql>insert into worker set name=’tom’;
在 SET 子句中未命名的行都赋予一个缺省值。
使用这种形式的 INSERT 语句不能插入多行。
l 一个expression可以引用在一个值表先前设置的任何列。例如,你能这样:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
但不能这样:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
3.5.2 使用Insert…Select语句插入从其他表选择的行
当我们在上一节学习创建表时,知道可以使用select从其它表来直接创建表,甚至可以同时复制数据记录。如果你已经拥有了一个表,你同样可以从select语句的配合中获益。
从其它表中录入数据,例如:
mysql>insert into tbl_name1(col1,col2) select col3,col4 from tbl_name2;
你也可以略去目的表的列列表,如果你每一列都有数据录入。
mysql>insert into tbl_name1 select col3,col4 from tbl_name2;
INSERT INTO ... SELECT语句满足下列条件:
l 查询不能包含一个ORDER BY子句。
l INSERT语句的目的表不能出现在SELECT查询部分的FROM子句,因为这在ANSI SQL中被禁止让从你正在插入的表中SELECT。(问题是SELECT将可能发现在同一个运行期间内先前被插入的记录。当使用子选择子句时,情况能很容易混淆)
3.5.3 使用replace、replace…select语句插入
REPLACE功能与INSERT完全一样,除了如果在表中的一个老记录具有在一个唯一索引上的新记录有相同的值,在新记录被插入之前,老记录被删除。对于这种情况,insert语句的表现是产生一个错误。
REPLACE语句也可以褐SELECT相配合,所以上两小节的内容完全适合REPALCE.。
应该注意的是,由于REPLACE语句可能改变原有的记录,因此使用时要小心。
3.5.4 使用LOAD语句批量录入数据
本章的前面讨论如何使用SQL向一个表中插入数据。但是,如果你需要向一个表中添加许多条记录,使用SQL语句输入数据是很不方便的。幸运的是,MySQL提供了一些方法用于批量录入数据,使得向表中添加数据变得容易了。本节以及下一节,将介绍这些方法。本节将介绍SQL语言级的解决方法。
1、基本语法
语法:LOAD DATA [LOCAL] INFILE \'file_name.txt\' [REPLACE | IGNORE] INTO TABLE tbl_name
LOAD DATA INFILE语句从一个文本文件中以很高的速度读入一个表中。如果指定LOCAL关键词,从客户主机读文件。如果LOCAL没指定,文件必须位于服务器上。(LOCAL在MySQL3.22.6或以后版本中可用。)
为了安全原因,当读取位于服务器上的文本文件时,文件必须处于数据库目录或可被所有人读取。另外,为了对服务器上文件使用LOAD DATA INFILE,在服务器主机上你必须有file的权限。见第七章 数据库安全。
REPLACE和IGNORE关键词控制对现有的唯一键记录的重复的处理。如果你指定REPLACE,新行将代替有相同的唯一键值的现有行。如果你指定IGNORE,跳过有唯一键的现有行的重复行的输入。如果你不指定任何一个选项,当找到重复键键时,出现一个错误,并且文本文件的余下部分被忽略时。
如果你使用LOCAL关键词从一个本地文件装载数据,服务器没有办法在操作的当中停止文件的传输,因此缺省的行为好像IGNORE被指定一样。
2、文件的搜寻原则
当在服务器主机上寻找文件时,服务器使用下列规则:
l 如果给出一个绝对路径名,服务器使用该路径名。
l 如果给出一个有一个或多个前置部件的相对路径名,服务器相对服务器的数据目录搜索文件。
l 如果给出一个没有前置部件的一个文件名,服务器在当前数据库的数据库目录寻找文件。
注意这些规则意味着一个像“./myfile.txt”给出的文件是从服务器的数据目录读取,而作为“myfile.txt”给出的一个文件是从当前数据库的数据库目录下读取。也要注意,对于下列哪些语句,对db1文件从数据库目录读取,而不是db2:
mysql> USE db1;
mysql> LOAD DATA INFILE "./data.txt" INTO TABLE db2.my_table;
3、FIELDS和LINES子句的语法
如果你指定一个FIELDS子句,它的每一个子句(TERMINATED BY, [OPTIONALLY] ENCLOSED BY和ESCAPED BY)也是可选的,除了你必须至少指定他们之一。
如果你不指定一个FIELDS子句,缺省值与如果你这样写的相同:
FIELDS TERMINATED BY \'\t\' ENCLOSED BY \'\' ESCAPED BY \'\\\'
如果你不指定一个LINES子句,缺省值与如果你这样写的相同:
LINES TERMINATED BY \'\n\'
换句话说,缺省值导致读取输入时,LOAD DATA INFILE表现如下:
l 在换行符处寻找行边界
l 在定位符处将行分进字段
l 不要期望字段由任何引号字符封装
l 将由“\”开头的定位符、换行符或“\”解释是字段值的部分字面字符
LOAD DATA INFILE能被用来读取从外部来源获得的文件。例如,以dBASE格式的文件将有由逗号分隔并用双引号包围的字段。如果文件中的行由换行符终止,下面显示的命令说明你将用来装载文件的字段和行处理选项:
mysql> LOAD DATA INFILE \'data.txt\' INTO TABLE tbl_name
FIELDS TERMINATED BY \',\' ENCLOSED BY \'"\'
LINES TERMINATED BY \'\n\';
任何字段或行处理选项可以指定一个空字符串(\'\')。如果不是空,FIELDS [OPTIONALLY] ENCLOSED BY和FIELDS ESCAPED BY值必须是一个单个字符。FIELDS TERMINATED BY和LINES TERMINATED BY值可以是超过一个字符。例如,写入由回车换行符对(CR+LF)终止的行,或读取包含这样行的一个文件,指定一个LINES TERMINATED BY \'\r\n\'子句。
FIELDS [OPTIONALLY] ENCLOSED BY控制字段的包围字符。对于输出(SELECT ... INTO OUTFILE),如果你省略OPTIONALLY,所有的字段由ENCLOSED BY字符包围。对于这样的输出的一个例子(使用一个逗号作为字段分隔符)显示在下面:
"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"
如果你指定OPTIONALLY,ENCLOSED BY字符仅被用于包围CHAR和VARCHAR字段:
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20
注意,一个字段值中的ENCLOSED BY字符的出现通过用ESCAPED BY字符作为其前缀来转义。也要注意,如果你指定一个空ESCAPED BY值,可能产生不能被LOAD DATA INFILE正确读出的输出。例如,如果转义字符为空,上面显示的输出显示如下。注意到在第四行的第二个字段包含跟随引号的一个逗号,它(错误地)好象要终止字段:
1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20
FIELDS ESCAPED BY控制如何写入或读出特殊字符。如果FIELDS ESCAPED BY字符不是空的,它被用于前缀在输出上的下列字符:
FIELDS ESCAPED BY字符
FIELDS [OPTIONALLY] ENCLOSED BY字符
FIELDS TERMINATED BY和LINES TERMINATED BY值的第一个字符
ASCII 0(实际上将后续转义字符写成 ASCII\'0\',而不是一个零值字节)
如果FIELDS ESCAPED BY字符是空的,没有字符被转义。指定一个空转义字符可能不是一个好主意,特别是如果在你数据中的字段值包含刚才给出的表中的任何字符。
对于输入,如果FIELDS ESCAPED BY字符不是空的,该字符的出现被剥去并且后续字符在字面上作为字段值的一个部分。例外是一个转义的“0”或“N”(即,\0或\N,如果转义字符是“\”)。这些序列被解释为ASCII 0(一个零值字节)和NULL。见下面关于NULL处理的规则。
3.5.5 总结
为数据库装载数据是管理员的重要职责之一,正因为重要,所以MySQL提供的方法也是非常繁多。其中主要的在本节已经列举:
1、 使用INSERT、REPLACE语句
2、 使用INSERT/REPLACE…SELECT语句
3、 使用LOAD DATA INFILE语句
4、 使用实用程序mysqlimport(将在第五章介绍)
3.6 查询数据表中的记录
除非最终检索它们并利用它们来做点事情,否则将记录放入数据库没什么好处。这就是 SELECT 语句的用途,即帮助取出数据。SELECT 大概是 SQL 语言中最常用的语句,而且怎样使用它也最为讲究;用它来选择记录可能相当复杂,可能会涉及许多表中列之间的比较。本节介绍Select语句关于查询的最基本功能。
SELECT 语句的语法如下:
SELECT selection_list 选择哪些列
FROM table_list 从何处选择行
WHERE primary_constraint 行必须满足什么条件
GROUP BY grouping_columns 怎样对结果分组
HAVING secondary_constraint 行必须满足的第二条件
ORDER BY sorting_columns 怎样对结果排序
LIMIT count 结果限定
注意:所有使用的关键词必须精确地以上面的顺序给出。例如,一个HAVING子句必须跟在GROUP BY子句之后和ORDER BY子句之前。
除了词“SELECT”和说明希望检索什么的 column_list 部分外,语法中的每样东西都是可选的。有的数据库还需要 FROM 子句。MySQL 有所不同,它允许对表达式求值而不引用任何表。
3.6.1 普通查询
l SELECT最简单的形式是从一张表中检索每样东西:
mysql> SELECT * FROM pet;
其结果为:
+----------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+------------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1990-08-31 | 1995-07-29 |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+--------+---------+------+------------+------------+
l 查询特定行:
你能从你的表中只选择特定的行。例如,如果你想要验证你对Bowser的出生日期所做的改变,像这样精选Bowser的记录:
mysql> SELECT * FROM pet WHERE name = "Bowser";
其结果为:
+--------+-------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog | m | 1990-08-31 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+
你可以对照前一个例子来验证。
l 查询特定列
如果你不想要看到你的表的整个行,就命名你感兴趣的列,用逗号分开。例如,如果你想要知道你的动物什么时候出生的,精选name和birth列:
mysql> SELECT name, birth FROM pet where owner="Gwen";
其结果为:
+----------+------------+
| name | birth |
+----------+------------+
| Claws | 1994-03-17 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
+----------+------------+
l 进行表达式计算
前面的多数查询通过从表中检索值已经产生了输出结果。MySQL 还允许作为一个公式的结果来计算输出列的值。表达式可以简单也可以复杂。下面的查询求一个简单表达式的值(常量)以及一个涉及几个算术运算符和两个函数调用的较复杂的表达式的值。例如,计算Browser生活的天数:
mysql> SELECT death-birth FROM pet WHERE name="Bowser";
其结果是:
+-------------+
| death-birth |
+-------------+
| 49898 |
+-------------+
由于MySQL允许对表达式求值而不引用任何表。所以也可以这样使用:
mysql>select (2+3*4.5)/2.5;
其结果为:
+---------------+
| (2+3*4.5)/2.5 |
+---------------+
| 6.200 |
+---------------+
3.6.2 条件查询
不必每次查询都返回所有的行记录,你能从你的表中只选择特定的行。为此你需要使用WHERE或者HAVING从句。HAVING从句与WHERE从句的区别是,HAVING表达的是第二条件,在与其他从句配合使用,显然不能在WHERE子句中的项目使用HAVING。因此本小节紧介绍WHERE从句的使用,HAVING从句的使用方法类似。另外WHERE从句也可以实现HAVING从句的绝大部分功能。
为了限制 SELECT 语句检索出来的记录集,可使用 WHERE 子句,它给出选择行的条件。可通过查找满足各种条件的列值来选择行。
WHERE 子句中的表达式可使用表1-1 中的算术运算符、表1-2 的比较运算符和表1-3 的逻辑运算符。还可以使用圆括号将一个表达式分成几个部分。可使用常量、表列和函数来完成运算。在本教程的查询中,我们有时使用几个 MySQL 函数,但是 MySQL 的函数远不止这里给出的这些。请参阅附录 一,那里给出了所有MySQL 函数的清单。
表3-1 算术运算符
|
运算符 |
说明 |
运算符 |
说明 |
|
+ |
加 |
* |
乘 |
|
- |
减 |
/ |
除 |
表3-2 比较运算符
|
运算符 |
说明 |
运算符 |
说明 |
|
< |
小于 |
!= 或 <> |
不等于 |
|
<= |
小于或等于 |
>= |
大于或等于 |
|
= |
等于 |
> |
大于 |
表3-3 逻辑运算符
|
运算符 |
说明 |
|
NOT或 ! |
逻辑非 |
|
OR 或 || |
逻辑或 |
|
AND或 && |
逻辑与 |
例如,如果你想要验证你对Bowser的出生日期所做的改变,像这样精选Bowser的记录:
mysql> SELECT * FROM pet WHERE name = "Bowser";
+--------+-------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog | m | 1990-08-31 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+
输出证实出生年份现在正确记录为1990,而不是1909。
字符串比较通常是大小些无关的,因此你可以指定名字为"bowser"、"BOWSER"等等,查询结果将是相同的。
你能在任何列上指定条件,不只是name。例如,如果你想要知道哪个动物在1998以后出生的,测试birth列:
mysql> SELECT * FROM pet WHERE birth >= "1998-1-1";
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+-------+---------+------+------------+-------+
你能组合条件,例如,找出雌性的狗:
mysql> SELECT * FROM pet WHERE species = "dog" AND sex = "f";
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
上面的查询使用AND逻辑操作符,也有一个OR操作符:
mysql> SELECT * FROM pet WHERE species = "snake" OR species = "bird";
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
+----------+-------+---------+------+------------+-------+
AND和OR可以混用。如果你这样做,使用括号指明条件应该如何被分组是一个好主意:
mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")
-> OR (species = "dog" AND sex = "f");
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
3.6.3 查询排序
使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
ORDER BY column_name [ASC|DESC] [,…]
其中ASC表示升序,为默认值,DESC为降序。ORDER BY不能按text、text和image数据类型进行排 序。另外,可以根据表达式进行排序。
例如,这里是动物生日,按日期排序:
mysql> SELECT name, birth FROM pet ORDER BY birth;
+----------+------------+
| name | birth |
+----------+------------+
| Buffy | 1989-05-13 |
| Fang | 1990-08-27 |
| Bowser | 1990-08-31 |
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Slim | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+
为了以逆序排序,增加DESC(下降 )关键字到你正在排序的列名上:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC;
+----------+------------+
| name | birth |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Claws | 1994-03-17 |
| Fluffy | 1993-02-04 |
| Bowser | 1990-08-31 |
| Fang | 1990-08-27 |
| Buffy | 1989-05-13 |
+----------+------------+
你能在多个列上排序。例如,按动物的种类排序,然后按生日,首先是动物种类中最年轻的动物,使用下列查询:
mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC;
+----------+---------+------------+
| name | species | birth |
+----------+---------+------------+
| Chirpy | bird | 1998-09-11 |
| Whistler | bird | 1997-12-09 |
| Claws | cat | 1994-03-17 |
| Fluffy | cat | 1993-02-04 |
| Bowser | dog | 1990-08-31 |
| Fang | dog | 1990-08-27 |
| Buffy | dog | 1989-05-13 |
| Puffball | hamster | 1999-03-30 |
| Slim | snake | 1996-04-29 |
+----------+---------+------------+
注意DESC关键词仅适用于紧跟在它之前的列名字(birth);species值仍然以升序被排序。注意,输出首先按照species排序,然后具有相同species的宠物再按照birth降序排列。
3.6.4 查询分组与行计数
GROUP BY 从句根据所给的列名返回分组的查询结果,可用于查询具有相同值的列。其语法为:
GROUP BY col_name,….
你可以为多个列分组。
例如:
mysql>select * from pet group by species;
+----------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+-------+
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
+----------+--------+---------+------+------------+-------+
由以上结果可以看出:
查询显示结果时,被分组的列如果有重复的值,只返回靠前的记录,并且返回的记录集是排序的。这并不是一个很好的结果。仅仅使用GROUP BY从句并没有什么意义,该从句的真正作用在于与各种组合函数配合,用于行计数。
1、COUNT()函数计数非NULL结果的数目。
你可以这样计算表中记录行的数目:
mysql> select count(*) from pet;
+----------+
| count(*) |
+----------+
| 9 |
+----------+
计算sex为非空的记录数目:
mysql> select count(sex) from pet;
+------------+
| count(sex) |
+------------+
| 8 |
+------------+
现在配合GROUP BY 从句使用。
例如:要知道每个主人有多少宠物
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
+--------+----------+
| owner | COUNT(*) |
+--------+----------+
| Benny | 2 |
| Diane | 2 |
| Gwen | 3 |
| Harold | 2 |
+--------+----------+
又如,每种宠物的个数:
mysql> SELECT species,count(*) FROM pet GROUP BY species;
+---------+----------+
| species | count(*) |
+---------+----------+
| bird | 2 |
| cat | 2 |
| dog | 3 |
| hamster | 1 |
| snake | 1 |
+---------+----------+
如果你除了计数还返回一个列的值,那么必须使用GROU BY语句,否则无法计算记录。例如上例,使用GROUP BY对每个owner分组所有记录,没有它,你得到的一切是一条错误消息:
mysql> SELECT owner, COUNT(owner) FROM pet;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause
也可以根据多个列分组,例如:
按种类和性别组合的动物数量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex | COUNT(*) |
+---------+------+----------+
| bird | NULL | 1 |
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
| hamster | f | 1 |
| snake | m | 1 |
+---------+------+----------+
3.6.5 查询多个表
查询多个表,FROM子句列出表名,并用逗号分隔,因为查询需要从他们两个拉出信息。
当组合(联结-join)来自多个表的信息时,你需要指定在一个表中的记录怎样能匹配其它表的记录。这很简单,因为它们都有一个name列。查询使用WHERE子句基于name值来匹配2个表中的记录。
因为name列出现在两个表中,当引用列时,你一定要指定哪个表。这通过把表名附在列名前做到。
现在有一个event表:
mysql>select * from event;
+----------+------------+----------+-----------------------------+
| name | date | type | remark |
+----------+------------+----------+-----------------------------+
| Fluffy | 1995-05-15 | litter | 4 kittens, 3 female, 1 male |
| Buffy | 1993-06-23 | litter | 5 puppies, 2 female, 3 male |
| Buffy | 1994-06-19 | litter | 3 puppies, 3 female |
| Chirpy | 1999-03-21 | vet | needed beak straightened |
| Slim | 1997-08-03 | vet | broken rib |
| Bowser | 1991-10-12 | kennel | NULL |
| Fang | 1991-10-12 | kennel | NULL |
| Fang | 1998-08-28 | birthday | Gave him a new chew toy |
| Claws | 1998-03-17 | birthday | Gave him a new flea collar |
| Whistler | 1998-12-09 | birthday | First birthday |
+----------+------------+----------+-----------------------------+
当他们有了一窝小动物时,假定你想要找出每只宠物的年龄。 event表指出何时发生,但是为了计算母亲的年龄,你需要她的出生日期。既然它被存储在pet表中,为了查询你需要两张表:
mysql> SELECT pet.name, (TO_DAYS(date) - TO_DAYS(birth))/365 AS age, remark
-> FROM pet, event
-> WHERE pet.name = event.name AND type = "litter";
+--------+------+-----------------------------+
| name | age | remark |
+--------+------+-----------------------------+
| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |
| Buffy | 4.12 | 5 puppies, 2 female, 3 male |
| Buffy | 5.10 | 3 puppies, 3 female |
+--------+------+-----------------------------+
同样方法也可用于同一张表中,你不必有2个不同的表来执行一个联结。如果你想要将一个表的记录与同一个表的其他记录进行比较,联结一个表到自身有时是有用的。例如,为了在你的宠物之中繁殖配偶,你可以用pet联结自身来进行相似种类的雄雌配对:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
-> FROM pet AS p1, pet AS p2
-> WHERE p1.species = p2.species AND p1.sex = "f" AND p2.sex = "m";
+--------+------+--------+------+---------+
| name | sex | name | sex | species |
+--------+------+--------+------+---------+
| Fluffy | f | Claws | m | cat |
| Buffy | f | Fang | m | dog |
| Buffy | f | Bowser | m | dog |
+--------+------+--------+------+---------+
在这个查询中,我们为表名指定别名以便能引用列并且使得每一个列引用关联于哪个表实例更直观。
3.3.6总结
本文总结了SELECT语句检索记录的简单使用方法。其中涉及到的内容主要包括以下一些内容:
1、 WHERE从句的用法
2、 GROUP BY从句的用法
3、 ORDER BY从句的用法
4、 连接多个表的简单介绍
3.7 修改、删除数据记录
有时,希望除去某些记录或更改它们的内容。DELETE 和 UPDATE 语句令我们能做到这一点。
3.7.1 用update修改记录
UPDATE tbl_name SET 要更改的列
WHERE 要更新的记录
这里的 WHERE 子句是可选的,因此如果不指定的话,表中的每个记录都被更新。
例如,在pet表中,我们发现宠物Whistler的性别没有指定,因此我们可以这样修改这个记录:
mysql> update pet set sex=’f’ where name=” Whistler”;
3.7.2 用delete删除记录
DELETE 语句有如下格式:
DELETE FROM tbl_name WHERE 要删除的记录
WHERE 子句指定哪些记录应该删除。它是可选的,但是如果不选的话,将会删除所有的记录。这意味着最简单的 DELETE 语句也是最危险的。
这个查询将清除表中的所有内容。一定要当心!
为了删除特定的记录,可用 WHERE 子句来选择所要删除的记录。这类似于 SELECT 语句中的 WHERE 子句。
mysql> delete from pet where name=”Whistler”;
可以用下面的语句清空整个表:
mysql>delete from pet;
3.7.3 总结
本节介绍了两个SQL语句的用法。使用UPDATE和DELETE语句要十分小心,因为可能对你的数据造成危险。尤其是DELETE语句,很容易会删除大量数据。使用时,一定小心。
思考题
1、 请亲自按照本章所述的步骤,让MySQL服务器在Linux系统启动时,自动启动。并尝试其它启动、重启、关闭服务器的方法。
2、 现在有一个位于主机database.domain.net的MySQL服务器,用root用户的身份,密码为newpass,连接到数据库test。如何给出合适的命令行?如果使用选项文件,如何添加选项?
3、 在test数据库中建立一个本章举例中所述的表pet,其结构如下所述:
name:30个宽度的定长字符串
owner:30个宽度的定长字符串
species:10个宽度的定长字符串
sex:由m和f组成的非空枚举类型
birth:date类型
death:date类型
4、 本章中pet表的数据录入表中:
+----------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+------------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1990-08-31 | 1995-07-29 |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+--------+---------+------+------------+------------+
请把数据记录到一个数据文件中,然后使用LOAD DATA INFILE语句装载数据。提示:如果在Windows环境中,那么文件的换行符是”\r\n”。
如果是使用实用程序mysqlimport命令行如何书写。
5、重复本章中的3.6节对表pet进行检索的例子。
第1章