当前位置:文档之家› mysql自学教程

mysql自学教程

4. MySQL 程序概述 ?
Section Navigation
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
[Toggle]
前言 1. 一般信息 2. 安装 MySQL 3. 教程 4. MySQL 程序概述 5. 数据库管理 6. 中的复制 7. 优化 8. 客户端和实用工具程序 9.语言结构 10. 字符集支持 11. 列类型 12. 函数和操作符 13. SQL 语句语法 14. 插件式存储引擎体系结构 15. 存储引擎和表类型 16. 编写自定义存储引擎 17. MySQL 簇 18. 分区 19. 中的空间扩展 20. 存储程序和函数 21. 触发程序 22. 视图 23. INFORMATION_SCHEMA 信息数据库 24. 精度数学 25. API 和库 26. 连接器 27. 扩展 MySQL A. 问题和常见错误 B. 错误代码和消息 C. 感谢 D. MySQL 变更史 E. 移植到其他系统 F. 环境变量 G. 正则表达式 H. Limits in MySQL I. 特性限制 J. GNU 通用公共许可

? ?
K. MySQL FLOSS 许可例外 索引
第 3 章:教程
目录 3.1. 连接与断开服务器 3.2. 输入查询 3.3. 创建并使用数据库 3.3.1. 创建并选择数据库 3.3.2. 创建表 3.3.3. 将数据装入表中 3.3.4. 从表检索信息 3.4. 获得数据库和表的信息 3.5. 在批处理模式下使用 mysql 3.6. 常用查询的例子 3.6.1. 列的最大值 3.6.2. 拥有某个列的最大值的行 3.6.3. 列的最大值:按组 3.6.4. 拥有某个字段的组间最大值的行 3.6.5. 使用用户变量 3.6.6. 使用外键 3.6.7. 根据两个键搜索 3.6.8. 根据天计算访问量 3.6.9. 使用 AUTO_INCREMENT 3.7. 孪生项目的查询 3.7.1. 查找所有未分发的孪生项 3.7.2. 显示孪生对状态的表 3.8. 与 Apache 一起使用 MySQL 本章通过演示如何使用 mysql 客户程序创造和使用一个简单的数据库,提供一个 MySQL 的入门教程。mysql(有时称为“终端监视器”或只是“监视”)是一个交互式程 序,允许你连接一个 MySQL 服务器,运行查询并察看结果。mysql 可以用于批模 式:你预先把查询放在一个文件中,然后告诉 mysql 执行文件的内容。本章将介绍使 用 mysql 的两个方法。 要想查看由 mysql 提供的选择项目表,可以用--help 选项来调用:
shell>
mysql
--help
本章假定 mysql 已经被安装在你的机器上,并且有一个 MySQL 服务器可以连接。否 则,请联络 MySQL 管理员。(如果你是管理员,则需要查阅本手册的其它章节,例如 第 5 章:数据库管理。) 本章描述建立和使用一个数据库的全过程。如果你仅仅对访问一个已经存在的数据库感兴 趣,可以跳过描述怎样创建数据库及它所包含的表的章节。

由于本章是一个教程,省略了许多细节。关于这里所涉及的主题的详细信息,请查阅本手 册的相关章节。
3.1. 连接与断开服务器
为了连接服务器,当调用 mysql 时,通常需要提供一个 MySQL 用户名并且很可能需 要一个 密码。如果服务器运行在登录服务器之外的其它机器上,还需要指定主机名。联系 管理员以找出进行连接所使用的参数 (即,连接的主机、用户名和使用的密码)。知道正确 的参数后,可以按照以下方式进行连接:
shell> mysql -h host -u user -p Enter password: ********
host 和 user 分别代表 MySQL 服务器运行的主机名和 MySQL 账户用户名。设置时替 换为正确的值。******** 代表你的密码;当 mysql 显示 Enter password:提示时输入它。 如果有效,你应该看见 mysql>提示符后的一些介绍信息:
shell> mysql -h host -u user -p Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 25338 to server version: 5.1.2-alphastandard Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> mysql> 提示符告诉你 mysql 准备为你输入命令。
一些 MySQL 安装允许用户以匿名(未命名)用户连接到本地主机上运行的服务器。如 果你的机器是这种情况,你应该能不带任何选项地调用 mysql 与该服务器连接:
shell>
mysql
成功地连接后,可以在 mysql>提示下输入 QUIT (或\q)随时退出:
mysql>
Bye
QUIT
在 Unix 中,也可以按 control-D 键断开服务器。 在下列章节的大多数例子都假设你连接到了服务器。由 mysql>提示指明。
3.2. 输入查询
确保你连接上了服务器,如在先前的章节讨论的。连接上服务器并布代表选择了任何数据 库,但这样就可以了。知道关于如何查询的基本知识,比马上跳至创建表、给他们装载数 据并且从他们检索数据更重要。本节描述输入命令的基本原则,使用几个查询,你能尝试 了解 mysql 是如何工作的。

这是一个简单的命令,要求服务器告诉它的版本号和当前日期。在 mysql>提示输入如 下命令并按回车键:
mysql>
SELECT VERSION(), CURRENT_DATE; +-----------------+--------------+ | VERSION() | CURRENT_DATE | +-----------------+--------------+ | 5.1.2-alpha-log | 2005-10-11 | +-----------------+--------------+ 1 row in set (0.01 sec) mysql>
这询问说明 mysql 的几个方面: · 一个命令通常由 SQL 语句组成,随后跟着一个分号。(有一些例外不需要分号。早 先提到的 QUIT 是一个例子。后面我们将看到其它的例子。) 当发出一个命令时,mysql 将它发送给服务器并显示执行结果,然后显示另一个 mysql>显示它准备好接受其它命令。 · · mysql 用表格(行和列)方式显示查询输出。第一行包含列的标签,随后的行是查 询结果。通常,列标签是你取自数据库表的列的名字。如果你正在检索一个表达式而非表 列的值(如刚才的例子),mysql 用表达式本身标记列。 · mysql 显示返回了多少行,以及查询花了多长时间,它给你提供服务器性能的一 个大致概念。因为他们表示时钟时间(不是 CPU 或机器时间),并且因为他们受到诸如服务 器负载和网络延时的影响,因此这些值是不精确的。(为了简洁,在本章其它例子中不再 显示“集合中的行”。) 能够以大小写输入关键词。下列查询是等价的:
mysql> mysql> mysql>
SELECT VERSION(), CURRENT_DATE; select version(), current_date; SeLeCt vErSiOn(), current_DATE;
这是另外一个查询,它说明你能将 mysql 用作一个简单的计算器:
mysql>
SELECT SIN(PI()/4), (4+1)*5; +------------------+---------+ | SIN(PI()/4) | (4+1)*5 | +------------------+---------+ | 0.70710678118655 | 25 | +------------------+---------+ 1 row in set (0.02 sec)
至此显示的命令是相当短的单行语句。你可以在一行上输入多条语句,只需要以一个分号 间隔开各语句:
mysql>
SELECT VERSION(); SELECT NOW(); +-----------------+ | VERSION() | +-----------------+

| 5.1.2-alpha-log | +-----------------+ 1 row in set (0.00 sec) +---------------------+ | NOW() | +---------------------+ | 2005-10-11 15:15:00 | +---------------------+ 1 row in set (0.00 sec)
不必全在一个行内给出一个命令,较长命令可以输入到多个行中。mysql 通过寻找终止 分号而不是输入行的结束来决定语句在哪儿结束。(换句话说,mysql 接受自由格式的 输入:它收集输入行但直到看见分号才执行。) 这里是一个简单的多行语句的例子:
mysql>
SELECT -> USER() -> , -> CURRENT_DATE; +---------------+--------------+ | USER() | CURRENT_DATE | +---------------+--------------+ | jon@localhost | 2005-10-11 | +---------------+--------------+
在这个例子中,在输入多行查询的第一行后,要注意提示符如何从 mysql>变为->,这 正是 mysql 如何指出它没见到完整的语句并且正在等待剩余的部分。提示符是你的朋 友,因为它提供有价值的反馈,如果使用该反馈,将总是知道 mysql 正在等待什么。 如果你决定不想执行正在输入过程中的一个命令,输入\c 取消它:
mysql>
SELECT -> USER() -> \c mysql>
这里也要注意提示符,在你输入\c 以后,它切换回到 mysql>,提供反馈以表明 mysql 准备接受一个新命令。 下表显示出可以看见的各个提示符并简述它们所表示的 mysql 的状态: 提示符 含义 准备好接受新命令。 等待多行命令的下一行。 等待下一行,等待以单引号(“'”)开始的字符串的结束。 等待下一行,等待以双引号(“"”)开始的字符串的结束。 等待下一行,等待以反斜点(?`?)开始的识别符的结束。 等待下一行,等待以/*开始的注释的结束。
mysqL>
-> '> "> `> /*>

当你打算在一个单行上发出一个命令时,通常会“偶然”出现多行语句,但是没有终止分 号。在这种情况中,mysql 等待进一步输入:
mysql>
->
SELECT USER()
如果出现这种情况(你认为输完了语句,但是只有一个->提示符响应),很可能 mysql 正 在等待分号。如果你没有注意到提示符的提示,在意识到你需要做什么之前,你可能会呆 坐一会儿。输入一个分号完成语句,mysql 将执行:
mysql>
SELECT USER() -> ; +---------------+ | USER() | +---------------+ | jon@localhost | +---------------+
在字符串收集期间将出现 '> 和 "> 提示符(提示 MySQL 正等待字符串的结束)。在 MySQL 中,可以写由?'?或?"?字符括起来的字符串 (例如,'hello'或"goodbye"),并且 mysql 允许输入跨越多行的字符串。当看到一个 '> 或 "> 提示符时,这意味着已经输入 了包含以?'?或?"?括号字符开始的字符串的一行,但是还没有输入终止字符串的匹配引号。这 显示你粗心地省掉了一个引号字符。例如:
mysql>
'>
SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
如果你输入 SELECT 语句,然后按 Enter(回车)键并等待结果,什么都没有出现。不要 惊讶,“为什么该查询这么长呢?”,注意">提示符提供的线索。它告诉你 mysql 期望见 到一个未终止字符串的余下部分。(你看见语句中的错误吗?字符串"Smith 丢掉了第二个 引号。) 走到这一步,你该做什么?最简单的是取消命令。然而,在这种情况下,你不能只是输入 \c,因为 mysql 作为它正在收集的字符串的一部分来解释它!相反,应输入关闭的引号 字符(这样 mysql 知道你完成了字符串),然后输入\c:
mysql>
SELECT * FROM my_table WHERE name = 'Smith AND age < 30; '> '\c mysql>
提示符回到 mysql>,显示 mysql 准备好接受一个新命令了。 `> 提示符类似于 '> 和"> 提示符,但表示你已经开始但没有结束以`> 开始的识别符。 知道'>和">提示符的含义很重要,因为如果你错误地输入一个未终止的字符串,任何后面 输入的行将要被 mysql 忽略--包括包含 QUIT 的行!这可能令人相当困惑,特别是如果 取消当前命令前还不知道你需要提供终止引号。
3.3. 创建并使用数据库

3.3.1. 创建并选择数据库 3.3.2. 创建表 3.3.3. 将数据装入表中 3.3.4. 从表检索信息 知道怎样输入命令,便可以访问数据库了。 假定在你的家(你的“动物园”)中有很多宠物,并且你想跟踪关于它们各种类型的信息。你可 以通过创建表来保存你的数据并根据所需要的信息装载他们,然后你可以从表中检索数据 来回答关于动物不同种类的问题。本节显示如何做到所有这些事情: · · · · · 创建数据库 创建数据库表 装载数据到数据库表 以各种方法从表中检索数据 使用多个表
动物园数据库很简单(特意的),但是不难把它想象成可能用到类似数据库的真实世界情 况。例如,农夫可以使用这样的一个数据库来追踪家畜,或者兽医可以用它跟踪病畜记 录。从 MySQL 网址上可以获得后面章节中将用到的含有部分查询和样例数据的动物园 分发。有 tar 压缩格式 (https://www.doczj.com/doc/f717496506.html,/docs/menagerie-db.tar.gz)和 Zip 压缩格式 (https://www.doczj.com/doc/f717496506.html,/docs/menagerie-db.zip)。 使用 SHOW 语句找出服务器上当前存在什么数据库:
mysql>
SHOW DATABASES; +----------+ | Database | +----------+ | mysql | | test | | tmp | +----------+
可能你的机器上的数据库列表是不同的,但是很可能有 mysql 和 test 数据库。 mysql 是必需的,因为它描述用户访问权限,test 数据库经常作为用户试身手的工作 区。 请注意如果没有 SHOW DATABASES 权限,则不能看见所有数据库。参见 13.5.1.3 节, “GRANT 和 REVOKE 语法”。 如果 test 数据库存在,尝试访问它:
mysql>
USE test Database changed

注意,USE,类似 QUIT,不需要一个分号。(如果你喜欢,你可以用一个分号终止这样 的语句;这无碍)USE 语句在使用上也有另外一个特殊的地方:它必须在一个单行上给 出。 你可列在后面的例子中使用 test 数据库(如果你能访问它),但是你在该数据库创建的任何 东西可以被访问它的其它人删除,因此,你应该询问 MySQL 管理员许可你使用自己的 一个数据库。假定你想要调用你的 menagerie,管理员需要执行这样一条命令:
mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';
这里 your_mysql_name 是分配给你的 MySQL 用户名,your_client_host 是所连接的 服务器所在的主机。
3.3.1. 创建并选择数据库
如果管理员在设置权限时为你创建了数据库,你可以开始使用它。否则,你需要自己创建 数据库:
mysql>
CREATE DATABASE menagerie;
在 Unix 下,数据库名称是区分大小写的(不像 SQL 关键字),因此你必须总是以 menagerie 访问数据库,而不能用 Menagerie、MENAGERIE 或其它一些变量。对表名也 是这样的。(在 Windows 下,该限制不适用,尽管你必须在一个给定的查询中使用同样的 大小写来引用数据库和表。但是,由于多种原因,作为最好的惯例,一定要使用与数据库 创建时的同样的大小写。) 创建数据库并不表示选定并使用它,你必须明确地操作。为了使 menagerie 成为当前的数 据库,使用这个命令:
mysql>
USE menagerie Database changed
数据库只需要创建一次,但是必须在每次 启动 mysql 会话时在使用前先选择它。你可以根据上面的例子执行一个 USE 语句来实 现。还可以在调用 mysql 时,通过命令行选择数据库,只需要在提供连接参数之后指 定数据库名称。例如:
shell> mysql -h host -u user -p menagerie Enter password: ********
注意,刚才显示的命令行中的 menagerie 不是你的 密码。如果你想要在命令行上在-p 选 项后提供 密码,则不能插入空格(例如,如-pmypassword,不是-p mypassword)。但是, 不建议在命令行输入密码,因为这样会暴露 密码,能被在机器上登录的其它用户窥探到。
3.3.2. 创建表
创建数据库是很容易的部分,但是在这时它是空的,正如 SHOW TABLES 将告诉你的:

mysql>
SHOW TABLES; Empty set (0.00 sec)
较难的部分是决定你的数据库结构应该是什么:你需要什么数据库表,各数据库表中有什 么样的列。 你将需要一个包含你每个宠物的记录的表。它可称为 pet 表,并且它应该包含,最少,每 个动物的名字。因为名字本身不是很有趣,表应该包含另外的信息。例如,如果在你豢养 宠物的家庭有超过一个人,你可能想要列出每个动物的主人。你可能也想要记录例如种类 和性别的一些基本的描述信息。 年龄呢?那可能有趣,但是存储到一个数据库中不是一件好事情。年龄随着时间流逝而变 化,这意味着你将要不断地更新你的记录。相反, 存储一个固定值例如生日比较好,那 么,无论何时你需要年龄,可以以当前日期和出生日期之间的差来计算它。MySQL 提供 了日期运算函数,因此这并不困难。存储出生日期而非年龄还有其它优点: · 你可以使用数据库完成这样的任务,例如生成即将到来的宠物生日的提示。(如果 你认为这类查询有点蠢,注意,这与从商务数据库来识别出不久要发给生日祝贺的客户是 同一个问题,因为计算机帮助私人联络。) · 你可以相对于日期而不止是当前日期来计算年龄。例如,如果你在数据库存储死亡 日期,你能很容易地计算出一只宠物死时有多大。 你可能想到 pet 表中其它有用的其它类型信息,但是到目前为止这些已经足够了:名字、 主人、种类,性别、出生和死亡日期。 使用一个 CREATE TABLE 语句指定你的数据库表的布局:
mysql>
CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
VARCHAR 适合于 name、owner 和 species 列,因为列值是变长的。这些列的长度不必 都相同,而且不必是 20。你可以挑选从 1 到 65535 的任何长度,从中选择一个最合理的 值。(如果选择得不合适,后来证明你需要一个更长的字段,MySQL 提供一个 ALTER TABLE 语句。) 可以用多种类型的值来表示动物记录中的性别,例如,"m"和"f",或"male"和"female"。使 用单字符"m"和"f"是最简单的方法。 很显然,birth 和 death 列应选用 DATE 数据类。 创建了数据库表后,SHOW TABLES 应该产生一些输出:
mysql>
SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | pet | +---------------------+
为了验证你的表是按你期望的方式创建,使用一个 DESCRIBE 语句:

mysql>
DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | owner | varchar(20) | YES | | NULL | | | species | varchar(20) | YES | | NULL | | | sex | char(1) | YES | | NULL | | | birth | date | YES | | NULL | | | death | date | YES | | NULL | | +---------+-------------+------+-----+---------+-------+
你可以随时使用 DESCRIBE,例如,如果你忘记表中的列的名称或类型时。
3.3.3. 将数据装入表中
创建表后,需要填入内容。通过 LOAD DATA 和 INSERT 语句可以完成该任务。 假定你的宠物纪录描述如下。(假定在 MySQL 中期望的日期格式是 YYYY-MM-DD;这 可能与你习惯的不同。) name Fluffy Claws Buffy Fang Bowser Chirpy Whistler Slim owner Harold Gwen Harold Benny Diane Gwen Gwen Benny species cat cat dog dog dog bird bird snake m sex f m f m m f birth 1993-0204 1994-0317 1989-0513 1990-0827 1979-0831 1998-0911 1997-1209 1996-0429 1995-0729 death
因为你是从一个空表开始的,填充它的一个简易方法是创建一个文本文件,每个动物各一 行,然后用一个语句将文件的内容装载到表中。 你可以创建一个文本文件“pet.txt”,每行包含一个记录,用定位符(tab)把值分开,并 且以 CREATE TABLE 语句中列出的列次序给出。对于丢失的值(例如未知的性别,或仍然 活着的动物的死亡日期),你可以使用 NULL 值。为了在你的文本文件中表示这些内容,使 用\N(反斜线,字母 N)。例如,Whistler 鸟的记录应为(这里值之间的空白是一个定位 符): name Whistler owner Gwen species bird sex \N birth 1997-12death \N

09 要想将文本文件“pet.txt”装载到 pet 表中,使用这个命令:
mysql>
LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
请注意如果用 Windows 中的编辑器(使用\r\n 做为行的结束符)创建文件,应使用:
mysql>
LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet -> LINES TERMINATED BY '\r\n';
(在运行 OS X 的 Apple 机上,应使用行结束符'\r'。) 如果你愿意,你能明确地在 LOAD DATA 语句中指出列值的分隔符和行尾标记,但是默认 标记是定位符和换行符。这对读入文件“pet.txt”的语句已经足够。 如果该语句失败,可能是你安装的 MySQL 不与使用默认值的本地文件兼容。关于如何 更改请参见 5.6.4 节,“LOAD DATA LOCAL 安全问题”。 如果想要一次增加一个新记录,可以使用 INSERT 语句。最简单的形式是,提供每一列的 值,其顺序与 CREATE TABLE 语句中列的顺序相同。假定 Diane 把一只新仓鼠命名为 Puffball,你可以使用下面的 INSERT 语句添加一条新记录:
mysql>
INSERT INTO pet -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
注意,这里字符串和日期值均为引号扩起来的字符串。另外,可以直接用 INSERT 语句插 入 NULL 代表不存在的值。不能使用 LOAD DATA 中所示的的\N。 从这个例子,你应该能看到涉及很多的键入用多个 INSERT 语句而非单个 LOAD DATA 语 句装载你的初始记录。
3.3.4. 从表检索信息
3.3.4.1. 选择所有数据 3.3.4.2. 选择特殊行 3.3.4.3. 选择特殊列 3.3.4.4. 分类行 3.3.4.5. 日期计算 3.3.4.6. NULL 值操作 3.3.4.7. 模式匹配 3.3.4.8. 计数行 3.3.4.9. 使用 1 个以上的表 SELECT 语句用来从数据表中检索信息。语句的一般格式是:
SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;

what_to_select 指出你想要看到的内容,可以是列的一个表,或*表示“所有的列”。 which_table 指出你想要从其检索数据的表。WHERE 子句是可选项,如果选择该项, conditions_to_satisfy 指定行必须满足的检索条件。
3.3.4.1. 选择所有数据
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 | | Fang | Benny | dog | m | 1990-08-27 | NULL | | Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 | | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+--------+---------+------+------------+------------+
如果你想要浏览整个表,可以使用这种形式的 SELECT,例如,刚刚装载了初始数据集以 后。也有可能你想到 Bowser 的生日看起来不很对。查阅你原来的家谱,你发现正确的出 生年是 1989,而不是 1979。 至少有两种修正方法: · 编辑文件“pet.txt”改正错误,然后使用 DELETE 和 LOAD DATA 清空并重新 装载表:
· · pet;
mysql> mysql>
DELETE FROM pet; LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE
然而, 如果这样操做,必须重新输入 Puffball 记录。 · 用一个 UPDATE 语句仅修正错误记录:
· name = 'Bowser';
mysql>
UPDATE pet SET birth = '1989-08-31' WHERE
UPDATE 只更改有问题的记录,不需要重新装载数据库表。
3.3.4.2. 选择特殊行
如上所示,检索整个表是容易的。只需要从 SELECT 语句中删掉 WHERE 子句。但是一 般你不想看到整个表,特别地当表变得很大时。相反,你通常对回答一个具体的问题更感 兴趣,在这种情况下在你想要的信息上进行一些限制。让我们看一些他们回答的有关你宠 物的问题的选择查询。

可以从表中只选择特定的行。例如,如果你想要验证你对 Bowser 的生日所做的更改,按 下述方法选择 Bowser 的记录:
mysql>
SELECT * FROM pet WHERE name = 'Bowser'; +--------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+-------+---------+------+------------+------------+ | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+-------+---------+------+------------+------------+
输出证实正确的年份记录为 1989,而不是 1979。 字符串比较时通常对大小些不敏感,因此你可以将名字指定为"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 可以混用,但 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.3.4.3. 选择特殊列
如果你不想看到表中的所有行,就命名你感兴趣的列,用逗号分开。例如,如果你想要知 道你的动物什么时候出生的,选择 name 和 birth 列:
mysql>
SELECT name, birth FROM pet; +----------+------------+ | name | birth | +----------+------------+ | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Buffy | 1989-05-13 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Puffball | 1999-03-30 | +----------+------------+
找出谁拥有宠物,使用这个查询:
mysql>
SELECT owner FROM pet; +--------+ | owner | +--------+ | Harold | | Gwen | | Harold | | Benny | | Diane | | Gwen | | Gwen | | Benny | | Diane | +--------+
请注意该查询只是简单地检索每个记录的 owner 列,并且他们中的一些出现多次。为了使 输出减到最少,增加关键字 DISTINCT 检索出每个唯一的输出记录:
mysql>
SELECT DISTINCT owner FROM pet; +--------+ | owner | +--------+ | Benny | | Diane | | Gwen | | Harold | +--------+
可以使用一个 WHERE 子句结合行选择与列选择。例如,要想查询狗和猫的出生日期,使 用这个查询:

mysql>
SELECT name, species, birth FROM pet -> WHERE species = 'dog' OR species = 'cat'; +--------+---------+------------+ | name | species | birth | +--------+---------+------------+ | Fluffy | cat | 1993-02-04 | | Claws | cat | 1994-03-17 | | Buffy | dog | 1989-05-13 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | +--------+---------+------------+
3.3.4.4. 分类行
你可能已经注意到前面的例子中结果行没有以特定的顺序显示。然而,当行按某种方式排 序时,检查查询输出通常更容易。为了排序结果,使用 ORDER BY 子句。 这里是动物生日,按日期排序:
mysql>
SELECT name, birth FROM pet ORDER BY birth; +----------+------------+ | name | birth | +----------+------------+ | Buffy | 1989-05-13 | | Bowser | 1989-08-31 | | Fang | 1990-08-27 | | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Slim | 1996-04-29 | | Whistler | 1997-12-09 | | Chirpy | 1998-09-11 | | Puffball | 1999-03-30 | +----------+------------+
在字符类型列上,与所有其他比较操作类似,分类功能正常情况下是以区分大小写的方式 执行的。这意味着,对于等同但大小写不同的列,并未定义其顺序。对于某一列,可以使 用 BINARY 强制执行区分大小写的分类功能,如:ORDER BY BINARY col_name. 默认排序是升序,最小的值在第一。要想以降序排序,在你正在排序的列名上增加 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 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | 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 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | | Buffy | dog | 1989-05-13 | | Puffball | hamster | 1999-03-30 | | Slim | snake | 1996-04-29 | +----------+---------+------------+
注意 DESC 关键字仅适用于在它前面的列名(birth);不影响 species 列的排序顺序。
3.3.4.5. 日期计算
MySQL 提供了几个函数,可以用来计算日期,例如,计算年龄或提取日期部分。
要想确定每个宠物有多大,可以计算当前日期的年和出生日期之间的差。如果当前日期的 日历年比出生日期早,则减去一年。以下查询显示了每个宠物的出生日期、当前日期和年 龄数值的年数字。
mysql>
SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5) AS age -> FROM pet; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | +----------+------------+------------+------+
此处,YEAR()提取日期的年部分,RIGHT()提取日期的 MM-DD (日历年)部分的最右面 5 个字符。比较 MM-DD 值的表达式部分的值一般为 1 或 0,如果 CURDATE()的年比 birth 的年早,则年份应减去 1。整个表达式有些难懂,使用 alias (age)来使输出的列标记更有 意义。

尽管查询可行,如果以某个顺序排列行,则能更容易地浏览结果。添加 ORDER BY name 子句按照名字对输出进行排序则能够实现。
mysql>
SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5) AS age -> FROM pet ORDER BY name; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | +----------+------------+------------+------+
为了按 age 而非 name 排序输出,只要再使用一个 ORDER BY 子句:
mysql>
SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5) AS age -> FROM pet ORDER BY age; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | +----------+------------+------------+------+
可以使用一个类似的查询来确定已经死亡动物的死亡年龄。你通过检查 death 值是否是 NULL 来确定是哪些动物,然后,对于那些非 NULL 值的动物,需要计算出 death 和 birth 值之间的差:
mysql>
SELECT name, birth, death, -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5) AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+ | name | birth | death | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+

查询使用 death IS NOT NULL 而非 death != NULL,因为 NULL 是特殊的值,不能使用普 通比较符来比较,以后会给出解释。参见 3.3.4.6 节,“NULL 值操作”。 如果你想要知道哪个动物下个月过生日,怎么办?对于这类计算,年和天是无关的,你只 需要提取 birth 列的月份部分。MySQL 提供几个日期部分的提取函数,例如 YEAR( )、 MONTH( )和 DAYOFMONTH( )。在这里 MONTH()是适合的函数。为了看它怎样工作,运 行一个简单的查询,显示 birth 和 MONTH(birth)的值:
mysql>
SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+ | name | birth | MONTH(birth) | +----------+------------+--------------+ | Fluffy | 1993-02-04 | 2 | | Claws | 1994-03-17 | 3 | | Buffy | 1989-05-13 | 5 | | Fang | 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | | Chirpy | 1998-09-11 | 9 | | Whistler | 1997-12-09 | 12 | | Slim | 1996-04-29 | 4 | | Puffball | 1999-03-30 | 3 | +----------+------------+--------------+
找出下个月生日的动物也是容易的。假定当前月是 4 月,那么月值是 4,你可以找在 5 月 出生的动物 (5 月),方法是:
mysql>
SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+
如果当前月份是 12 月,就有点复杂了。你不能只把 1 加到月份数(12)上并寻找在 13 月出 生的动物,因为没有这样的月份。相反,你应寻找在 1 月出生的动物(1 月) 。 你甚至可以编写查询,不管当前月份是什么它都能工作。采用这种方法不必在查询中使用 一个特定的月份,DATE_ADD( )允许在一个给定的日期上加上时间间隔。如果在 NOW( ) 值上加上一个月,然后用 MONTH()提取月份,结果产生生日所在月份:
mysql>
SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
完成该任务的另一个方法是加 1 以得出当前月份的下一个月(在使用取模函数(MOD)后,如 果月份当前值是 12,则“回滚”到值 0):
mysql>
SELECT name, birth FROM pet -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
注意,MONTH 返回在 1 和 12 之间的一个数字,且 MOD(something,12)返回在 0 和 11 之 间的一个数字,因此必须在 MOD( )以后加 1,否则我们将从 11 月( 11 )跳到 1 月(1)。

3.3.4.6. NULL 值操作
NULL 值可能令人感到奇怪直到你习惯它。概念上,NULL 意味着“没有值”或“未知值”,且 它被看作与众不同的值。为了测试 NULL,你不能使用算术比较 操作符例如=、<或!=。为 了说明它,试试下列查询:
mysql>
SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+ | 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL | +----------+-----------+----------+----------+ | NULL | NULL | NULL | NULL | +----------+-----------+----------+----------+
很显然你不能通过这些比较得到有意义的结果。相反使用 IS NULL 和 IS NOT NULL 操作 符:
mysql>
SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+ | 1 IS NULL | 1 IS NOT NULL | +-----------+---------------+ | 0 | 1 | +-----------+---------------+
请注意在 MySQL 中,0 或 NULL 意味着假而其它值意味着真。布尔运算的默认真值是 1。 对 NULL 的特殊处理即是在前面的章节中,为了决定哪个动物不再是活着的,使用 death IS NOT NULL 而不使用 death != NULL 的原因。 在 GROUP BY 中,两个 NULL 值视为相同。 执行 ORDER BY 时,如果运行 ORDER BY ... ASC,则 NULL 值出现在最前面,若运行 ORDER BY ... DESC,则 NULL 值出现在最后面。 NULL 操作的常见错误是不能在定义为 NOT NULL 的列内插入 0 或空字符串,但事实并非 如此。在 NULL 表示"没有数值"的地方有数值。使用 IS [NOT] NULL 则可以很容易地进行 测试,如下所示:
mysql>
SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL; +-----------+---------------+------------+----------------+ | 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL | +-----------+---------------+------------+----------------+ | 0 | 1 | 0 | 1 | +-----------+---------------+------------+----------------+
因此完全可以在定义为 NOT NULL 的列内插入 0 或空字符串,实际是 NOT NULL。参见 A.5.3 节,“与 NULL 值有关的问题”。
3.3.4.7. 模式匹配
MySQL 提供标准的 SQL 模式匹配,以及一种基于象 Unix 实用程序如 vi、grep 和 sed
的扩展正则表达式模式匹配的格式。

SQL 模式匹配允许你使用“_”匹配任何单个字符,而“%”匹配任意数目字符(包括零字 符)。在 MySQL 中,SQL 的模式默认是忽略大小写的。下面给出一些例子。注意使用 SQL 模式时,不能使用=或!=;而应使用 LIKE 或 NOT LIKE 比较操作符。 要想找出以“b”开头的名字:
mysql>
SELECT * FROM pet WHERE name LIKE 'b%'; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
要想找出以“fy”结尾的名字:
mysql>
SELECT * FROM pet WHERE name LIKE '%fy'; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
要想找出包含“w”的名字:
mysql>
SELECT * FROM pet WHERE name LIKE '%w%'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
要想找出正好包含 5 个字符的名字,使用“_”模式字符:
mysql>
SELECT * FROM pet WHERE name LIKE '_____'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
由 MySQL 提供的模式匹配的其它类型是使用扩展正则表达式。当你对这类模式进行匹 配测试时,使用 REGEXP 和 NOT REGEXP 操作符(或 RLIKE 和 NOT RLIKE,它们是同 义词)。 扩展正则表达式的一些字符是: · ?.?匹配任何单个的字符。

相关主题
文本预览
相关文档 最新文档