mysql常用命令汇总大全

    此文档通过演示如何使用 mysql 客户程序创造和使用一个简单的数据库提供一个 MySQL 的入门教程mysql  (有时称为终端监视器或只是监视是一个交互式程序允许你连 接一个 MySQL 服务器运行查询并察看结果mysql 可以用于此模式你预先把查询放在 一个文件中然后告诉 mysql 执行文件的内容本章将介绍使用 mysql 的两个方法

要想查看由 mysql 提供的选择项目表可以用--help 选项来调用

shell> mysql --help

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-alpha-standard

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

mysql> 提示符告诉你 mysql 准备为你输入命令

一些 MySQL 安装允许用户以匿名(未命名 用户连接到本地主机上运行的服务器如果你的 机器是这种情况你应该能不带任何选项地调用 mysql 与该服务器连接

shell> mysql

成功地连接后 可以在 mysql>提示下输入 QUIT (\q)随时退出

mysql> QUIT

Bye

 Unix 也可以按 control-D 键断开服务器

在下列章节的大多数例子都假设你连接到了服务器 mysql>提示指明

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> SELECT VERSION(), CURRENT_DATE;

mysql> select version(), current_date;

mysql> 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> 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.1. 创建并选择数据库

3.3.2. 创建表

3.3.3. 将数据装入表中

3.3.4. 从表检索信息

知道怎样输入命令 便可以访问数据库了

假定在你的家(你的动物园”)中有很多宠物 并且你想跟踪关于它们各种类型的信息你可 以通过创建表来保存你的数据并根据所需要的信息装载他们然后你可以从表中检索数据来 回答关于动物不同种类的问题本节显示如何做到所有这些事情

·        创建数据库

·        创建数据库表

·        装载数据到数据库表

·        以各种方法从表中检索数据

·        使用多个表

动物园数据库很简单(特意的)但是不难把它想象成可能用到类似数据库的真实世界情况 例如 农夫可以使用这样的一个数据库来追踪家畜,或者兽医可以用它跟踪病畜记录。从 MySQL 网址上可以获得后面章节中将用到的含有部分查询和样例数据的动物园分发 tar 压缩格式 (http://downloads.mysql.com/docs/menagerie-db.tar.gz) Zip 压缩格式

(http://downloads.mysql.com/docs/menagerie-db.zip)

使用 SHOW 语句找出服务器上当前存在什么数据库

mysql> SHOW DATABASES;

 

可能你的机器上的数据库列表是不同的 但是很可能有 mysql test 数据库mysql 是必 需的 因为它描述用户访问权限test 数据库经常作为用户试身手的工作区

请注意如果没有 SHOW DATABASES 权限则不能看见所有数据库

如果 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.1. 创建并选择数据库

如果管理员在设置权限时为你创建了数据库 你可以开始使用它否则 你需要 自己创建数据库

mysql> CREATE DATABASE menagerie;

Unix 数据库名称是区分大小写的(不像 SQL 关键字)因此你必须总是以 menagerie 访问数据库而不能用 MenagerieMENAGERIE 或其它一些变量对表名也是这样的 (在 Windows  该限制不适用尽管你必须在一个给定的查询中使用同样的大小写来引 用数据库和表但是由于多种原因作为最好的惯例 一定要使用与数据库创建时的同样 的大小写

创建数据库并不表示选定并使用它 你必须明确地操作为了使 menagerie 成为当前的数 据库 使用这个命令

mysql> USE menagerie

Database changed

数据库只需要创建一次 但是必须在每次启动 mysql 会话时在使用前先选择它你可以根 据上面的例子执行一个 USE 语句来实现还可以在调用 mysql 通过命令行选择数据库 只需要在提供连接参数之后指定数据库名称例如

shell> mysql -h host -u user

Enter password: ********

-p menagerie

注意 刚才显示的命令行中的 menagerie 是你的 密码如果你想要在命令行上在-p 选项 后提供 密码 则不能插入空格(例如 -pmypassword不是-p mypassword)但是不 建议在命令行输入密码 因为这样会暴露 密码 能被在机器上登录的其它用户窥探到

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),

-> speciesVARCHAR(20), sex CHAR(1),birth DATE, death DATE);

VARCHAR 适合于 nameowner 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;

 

你可以随时使用 DESCRIBE 例如如果你忘记表中的列的名称或类型时

3.3. 将数据装入表中

创建表后 需要填入内容通过 LOAD DATA INSERT 语句可以完成该任务

假定你的宠物纪录描述如下(假定在 MySQL 中期望的日期格式是 YYYY-MM-DD这可 能与你习惯的不同

 因为你是从一个空表开始的填充它的一个简易方法是创建一个文本文件每个动物各一行 然后用一个语句将文件的内容装载到表中


你可以创建一个文本文件 “pet.txt”每行包含一个记录 用定位符(tab)把值分开 并 且以 CREATE TABLE 语句中列出的列次序给出对于丢失的值(例如未知的性别 或仍然 活着的动物的死亡日期)你可以使用 NULL 为了在你的文本文件中表示这些内容 使 用\N(反斜线 字母 N)。例如 Whistler 鸟的记录应为(这里值之间的空白是一个定位符)因为你是从一个空表开始的填充它的一个简易方法是创建一个文本文件每个动物各一行 然后用一个语句将文件的内容装载到表中

要想将文本文件 “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”的语句已经足够

如果想要一次增加一个新记录 可以使用 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.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.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 清空并重新装

载表:

mysql> DELETE FROM pet;

mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;

然而, 如果这样操做 必须重新输入 Puffball 记录。

·        用一个 UPDATE 语句仅修正错误记录:

·               mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';

UPDATE 只更改有问题的记录 不需要重新装载数据库表

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');

 

 

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

| Claws  | cat

| Buffy  | dog

| Fang   | dog

| Bowser | dog

| 1993-02-04 |

| 1994-03-17 |

| 1989-05-13 |

| 1990-08-27 |

| 1989-08-31 |

+--------+---------+------------+

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.4.5. 日期计算

MySQL 提供了几个函数可以用来计算日期 例如计算年龄或提取日期部分

要想确定每个宠物有多大可以计算当前日期的年和出生日期之间的差如果当前日期的日 历年比出生日期早 则减去一年以下查询显示了每个宠物的出生日期当前日期和年龄数 值的年数字

mysql> SELECT name, birth, CURDATE(),

-> (YEAR(CURDATE())-YEAR(birth))

-> - (RIGHT(CURDATE(),5)<RIGHT(birth,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)<RIGHT(birth,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)<RIGHT(birth,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)<RIGHT(birth,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 是特殊的值不能使用普

通比较符来比较

如果你想要知道哪个动物下个月过生日怎么办? 对于这类计算年和天是无关的你只需 要提取 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.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 ... ASCNULL 值出现在最前面 若运行 ORDER BY ... DESCNULL 值出现在最后面

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

3.4.7. 模式匹配

MySQL 提供标准的 SQL 模式匹配 以及一种基于象 Unix 实用程序如vigrep sed 的 扩展正则表达式模式匹配的格式

SQL 模式匹配允许你使用 “_”匹配任何单个字符 “%”匹配任意数目字符(包括零字  符) MySQL  SQL 的模式默认是忽略大小写的下面给出一些例子注意使用 SQL 模式时不能使用=!=而应使用 LIKE NOT LIKE 比较操作符

要想找出以 “b”开头的名字

mysql> SELECT * FROM pet WHERE name LIKE 'b%';

 

要想找出以 “fy”结尾的名字

mysql> SELECT * FROM pet WHERE name LIKE '%fy';

要想找出包含“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 '_____';

 

 MySQL 提供的模式匹配的其它类型是使用扩展正则表达式当你对这类模式进行匹配测试 时使用 REGEXP NOT REGEXP 操作符(RLIKE NOT RLIKE它们是同义词)

扩展正则表达式的一些字符是

      „.‟匹配任何单个的字符

字符类“[...]”匹配在方括号内的任何字符例如  “[abc]”匹配“a”   “b”

或 “c”为了命名字符的范围 使用一个“-”   “[a-z]”匹配任何字母 而 “[0-9]”匹配

任何数字

·        “ * ”匹配零个或多个在它前面的字符例如  “x*”匹配任何数量的 “x”字符

    “[0-9]*”匹配任何数量的数字 “.*”匹配任何数量的任何字符

  如果 REGEXP 模式与被测试值的任何地方匹配 模式就匹配(这不同于 LIKE 模式匹配只有与整个值匹配模式才匹配)

  为了定位一个模式以便它必须匹配被测试值的开始或结尾 在模式开始处 使用 “^”或在模式的结尾用 “$”

为了说明扩展正则表达式如何工作 下面使用 REGEXP 重写上面所示的 LIKE 查询

为了找出以 “b”开头的名字使用“^”匹配名字的开始

mysql> SELECT * FROM pet WHERE name REGEXP '^b';

 

如果你想强制使 REGEXP 比较区分大小写使用 BINARY 关键字使其中一个字符串变为二 进制字符串该查询只匹配名称首字母的小写„b‟

mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';

为了找出以 “fy”结尾的名字使用 “$”匹配名字的结尾

mysql> SELECT * FROM pet WHERE name REGEXP 'fy$';

 

为了找出包含一个“w”的名字 使用以下查询

mysql> SELECT * FROM pet WHERE name REGEXP '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       |

+----------+-------+---------+------+------------+----------

--+

既然如果一个正则表达式出现在值的任何地方其模式匹配了就不必在先前的查询中在模 式的两侧放置一个通配符以使得它匹配整个值就像你使用了一个 SQL 模式那样

为了找出包含正好 5 个字符的名字使用 ^”和 $匹配名字的开始和结尾 5  . 实例在两者之间

mysql> SELECT * FROM pet WHERE name REGEXP '^.....$';

 

你也可以使用“{n}”重复 n 操作符重写前面的查询

mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$';

3.4.8. 计数行

数据库经常用于回答这个问题  “某个类型的数据在表中出现的频度?”例如 你可能想要知道你有多少宠物 或每位主人有多少宠物 或你可能想要对你的动 物进行各种类型的普查

计算你拥有动物的总数目与 pet 表中有多少行?”是同样的问题 因为每个宠物有一个记 录 COUNT(*)函数计算行数所以计算动物数目的查询应为

mysql> SELECT COUNT(*) FROM pet;

+----------+

| COUNT(*) |

+----------+

|        9 |

+----------+

在前面你检索了拥有宠物的人的名字如果你想要知道每个主人有多少宠物 你可以使用 COUNT( )函数

mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;

注意 使用 GROUP BY 对每个 owner 的所有记录分组 没有它 你会得到错误消息

mysql> SELECT owner, COUNT(*) FROM pet;

ERROR 1140 (42000): Mixing of GROUP columns

(MIN(),MAX(),COUNT(),...)

with no GROUP columns is illegal if there is no GROUP BY clause

COUNT( ) GROUP BY 以各种方式分类你的数据下列例子显示出进行动物普查操作的 不同方式

每种动物的数量

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;

 

每种性别的动物数量

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;

 

(在这个输出中NULL 表示未知性别。)

按种类和性别组合的动物数量

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 |

+---------+------+----------+

若使用 COUNT( )你不必检索整个表例如, 前面的查询, 当只对狗和猫进行时,应为:

mysql> SELECT species, sex, COUNT(*) FROM pet

-> WHERE species = 'dog' OR species = 'cat'

-> GROUP BY species, sex;

如果你仅需要知道已知性别的按性别的动物数目

mysql> SELECT species, sex, COUNT(*) FROM pet

-> WHERE sex IS NOT NULL

-> GROUP BY species, sex;

+---------+------+----------+

| species | sex  | COUNT(*) |

+---------+------+----------+

| bird    | f

|

1 |

| cat     | f

|

1 |

| cat     | m

|

1 |

| dog     | f

|

1 |

| dog     | m

|

2 |

| hamster | f

|

1 |

| snake   | m

|

1 |

+---------+------+----------+

3.4.9. 使用 1 个以上的表

pet 表追踪你有哪个宠物如果你想要记录其它相关信息 例如在他们一生中看 兽医或何时后代出生你需要另外的表这张表应该像什么呢?需要

·        它需要包含宠物名字以便你知道每个事件属于哪个动物

·        需要一个日期以便你知道事件是什么时候发生的

·        需要一个描述事件的字段

·        如果你想要对事件进行分类 则需要一个事件类型字段。

综合上述因素 event 表的 CREATE TABLE 语句应为

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,

-> type VARCHAR(15), remark VARCHAR(255));

对于 pet 最容易的方法是创建包含信息的用定位符分隔的文本文件来装载初始记录

采用如下方式装载记录

mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;

根据你从已经运行在 pet 表上的查询中学到的你应该能执行对 event 表中记录的检索理是一样的但是什么时候 event 表本身不能回答你可能问的问题呢?

当他们有了一窝小动物时假定你想要找出每只宠物的年龄我们前面看到了如何通过两个 日期计算年龄event 表中有母亲的生产日期但是为了计算母亲的年龄你需要她的出生 日期 存储在 pet 表中说明查询需要两个表

mysql> SELECT pet.name,

-> (YEAR(date)-YEAR(birth)) -

(RIGHT(date,5)<RIGHT(birth,5)) AS age,

-> remark

-> FROM pet, event

-> WHERE pet.name = event.name AND event.type = 'litter';

+--------+------+-----------------------------+

| name   | age  | remark                      |

+--------+------+-----------------------------+

| Fluffy |   2 | 4 kittens, 3 female, 1 male |

| Buffy  |    4 | 5 puppies, 2 female, 3 male |

| Buffy  |   5 | 3 puppies, 3 female         |

+--------+------+-----------------------------+

关于该查询要注意的几件事情

  FROM 子句列出两个表因为查询需要从两个表提取信息

  当从多个表组合(联结)信息时你需要指定一个表中的记录怎样能匹配其 它表的记录这很简单 因为它们都有一个 name 查询使用 WHERE 子 句基于 name 值来匹配 2 个表中的记录

  因为 name 列出现在两个表中当引用列时你一定要指定哪个表把表 名附在列名前即可以实现

你不必有 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';

在这个查询中我们为表名指定别名以便能引用列并且使得每一个列引用与哪个表实例相关 联更直观

4. 得数据库和表的信息

如果你忘记数据库或表的名字 或给定的表的结构是什么(例如它的列叫什么) 怎么办? MySQL 通过提供数据库及其支持的表的信息的几个语句解决这个问题

你已经见到了 SHOW DATABASES它列出由服务器管理的数据库为了找出当前选择了 哪个数据库使用 DATABASE( )函数

mysql> SELECT DATABASE();

+------------+

| DATABASE() |

+------------+

| menagerie  |

+------------+

如果你还没选择任何数据库结果是 NULL

为了找出当前的数据库包含什么表(例如 当你不能确定一个表的名字)使用这个命令

mysql> SHOW TABLES;

 

如果你想要知道一个表的结构 可以使用 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

|

|

+---------+-------------+------+-----+---------+-------+

Field 显示列名字 Type 是列的数据类型Null 表示列是否能包含 NULL  Key 显示列是 否被索引而 Default 指定列的默认值

如果表有索引 SHOW INDEX FROM tbl_name 生成有关索引的信息

5. 在批处理模式下使用mysql

在前面的章节中 你交互式地使用 mysql 输入查询并且查看结果你也可以以批 模式运行 mysql为了做到这些 把你想要运行的命令放在一个文件中 然后告  mysql 从文件读取它的输入

shell> mysql < batch-file

如果在 Windows 下运行 mysql并且文件中有一些可以造成问题的特殊字符可以这样操 作

C:\> mysql -e "source batch-file"

如果你需要在命令行上指定连接参数命令应为

shell> mysql -h host -u user -p < batch-file

Enter password: ********

当这样操作 mysql 则创建一个脚本文件 然后执行脚本

如果你想在语句出现错误的时候仍想继续执行脚本则应使用--force 命令行选项 什么要使用一个脚本? 有很多原因

  如果你需要重复运行查询(比如说每天或每周)可以把它编成一个脚本 则每次执行时不必重新键入

  可以通过拷贝并编辑脚本文件从类似的现有的查询生成一个新查询

  当你正在开发查询时 批模式也是很有用的 特别对多行命令或多语句命 令序列如果你犯了一个错误 你不必重新输入所有内容 只需要编辑脚 本来改正错误然后告诉 mysql 再次执行脚本

  如果你有一个产生多个输出的查询 你可以通过一个分页器而不是盯着它 翻屏到屏幕的顶端来运行输出

·                shell> mysql < batch-file | more

  你可以捕捉文件中的输出以便进行进一步的处理

·                shell> mysql < batch-file > mysql.out

  你可以将脚本分发给另外的人以便他们也能运行命令

  某些情况不允许交互地使用 例如, 当你从一个 cron 任务中运行查询时 在这种情况下你必须使用批模式

当你以批模式运行 mysql 比起你交互地使用它时其默认输出格式是不同的(更简明些) 例如 当交互式运行 SELECT DISTINCT species FROM pet 输出应为

 

但是当以批模式运行时 输出应为

如果你想要在批模式中得到交互输出格式使用 mysql -t 为了回显以输出被执行的命令 使用 mysql -vvv

你还可以使用源代码或 \.命令从 mysql 提示符运行脚本

mysql> source filename;

mysql> \. filename

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

下面是一些学习如何用 MySQL 解决一些常见问题的例子

在一些例子中使用数据库表“shop”来储存某个商人(经销商 的每件物品(物品号)的价格

假定每个商人对每项物品有一个固定价格那么(物品商人)即为该记录的主关键字 启动命令行工具 mysql 并选择数据库

shell> mysql your-database-name

(在大多数 MySQL 你可以使用 test 数据库)。

你可以使用以下语句创建示例表

mysql> CREATE TABLE shop (

-> article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,

-> dealer CHAR(20)                DEFAULT ''    NOT

NULL,

-> price  DOUBLE(16,2)            DEFAULT '0.00' NOT

NULL,

-> PRIMARY KEY(article, dealer));

mysql> INSERT INTO shop VALUES

-> (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),

-> (3,'C',1.69),(3,'D',1.25),(4,'D',19.95);

执行语句后表应包含以下内容

mysql> SELECT * FROM shop;

+---------+--------+-------+

| article | dealer | price |

+---------+--------+-------+

|

0001 | A

| 3.45 |

|

0001 | B

| 3.99 |

|

0002 | A

| 10.99 |

|

0003 | B

|  1.45 |

|

0003 | C

|  1.69 |

|

0003 | D

|  1.25 |

|

0004 | D

| 19.95 |

+---------+--------+-------+

6.1. 列的最大值

最大的物品号是什么?

SELECT MAX(article) AS article FROM shop;

 

6.2. 拥有某个列的最大值的行

任务找出最贵物品的编号销售商和价格

这很容易用一个子查询做到

SELECT article, dealer, price

FROM   shop

WHERE price=(SELECT MAX(price) FROM shop);

另一个解决方案是按价格降序排序所有行并用 MySQL 特定 LIMIT 子句只得到第一行

SELECT article, dealer, price

FROM shop

ORDER BY price DESC

LIMIT 1;

:如果有多项最贵的物品( 例如每个的价格为 19.95)LIMIT 解决方案仅仅显示其中一个!

6.3. 列的最大值按组

任务 每项物品的的最高价格是多少?

SELECT article, MAX(price) AS price

FROM  shop

GROUP BY article

 

6.4. 有某个字段的组间最大值的行

任务 对每项物品 找出最贵价格的物品的经销商

可以用这样一个子查询解决该问题

SELECT article, dealer, price

FROM  shop s1

WHERE price=(SELECT MAX(s2.price)

FROM shop s2

WHERE s1.article = s2.article);

6.5. 使用用户变量

你可以清空 MySQL 用户变量以记录结果不必将它们保存到客户端的临时变量中

例如 要找出价格最高或最低的物品的 其方法是

SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;

SELECT * FROM shop WHERE price=@min_price OR price=@max_price;

 

6.6. 使用外键

 MySQL  InnoDB 表支持对外部关键字约束条件的检查

只是联接两个表时 不需要外部关键字对于除 InnoDB 类型的表 当使用 REFERENCES tbl_name(col_name)子句定义列时可以使用外部关键字 该子句没有实际的效果 只作为 备忘录或注释来提醒你目前正定义的列指向另一个表中的一个列执行该语句时实现下 面很重要

·        MySQL 不执行表 tbl_name  中的动作 例如作为你正定义的表中的行的动作的响应

而删除行 换句话说该句法不会致使 ON DELETE ON UPDATE 行为(如果你在 REFERENCES 子句中写入 ON DELETE ON UPDATE 子句 将被忽略)。

该句法可以创建一个 column但不创建任何索引或关键字

如果用该句法定义 InnoDB 将会导致错误

你可以使用作为联接列创建的列如下所示

CREATE TABLE person (

id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,

name CHAR(60) NOT NULL,

PRIMARY KEY (id)

);

CREATE TABLE shirt (

id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,

style ENUM('t-shirt', 'polo', 'dress') NOT NULL,

color ENUM('red', 'blue', 'orange', 'white', 'black') NOT

NULL,

owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),

PRIMARY KEY (id)

);

INSERT INTO person VALUES (NULL, 'Antonio Paz');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES

(NULL, 'polo', 'blue', @last),

(NULL, 'dress', 'white', @last),

(NULL, 't-shirt', 'blue', @last);

INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');

SELECT @last := LAST_INSERT_ID();

INSERT INTO shirt VALUES

(NULL, 'dress', 'orange', @last),

(NULL, 'polo', 'red', @last),

(NULL, 'dress', 'blue', @last),

(NULL, 't-shirt', 'white', @last);

SELECT * FROM person;

+----+---------------------+

| id | name                |

+----+---------------------+

|  1 | Antonio Paz         |

| 2 | Lilliana Angelovska |

+----+---------------------+

SELECT * FROM shirt;

+----+---------+--------+-------+

| id | style   | color  | owner |

+----+---------+--------+-------+

|  1 | polo    | blue

|

1 |

| 2 | dress   | white

|

1 |

| 3 | t-shirt | blue

|

1 |

|  4 | dress   | orange

|

2 |

| 5 | polo    | red

|

2 |

|  6 | dress   | blue

|

2 |

|  7 | t-shirt | white

|

2 |

+----+---------+--------+-------+

SELECT s.* FROM person p, shirt s

WHERE p.name LIKE 'Lilliana%'

AND s.owner = p.id

AND s.color <> 'white';

 

按照这种方式使用 REFERENCES 子句不会显示在 SHOW CREATE TABLE DESCRIBE 的输出中:

SHOW CREATE TABLE shirt\G

*************************** 1. row

***************************

Table: shirt

Create Table: CREATE TABLE `shirt` (

`id` smallint(5) unsigned NOT NULL auto_increment,

`style` enum('t-shirt','polo','dress') NOT NULL,

`color` enum('red','blue','orange','white','black') NOT NULL,

`owner` smallint(5) unsigned NOT NULL,

PRIMARY KEY  (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=latin1

在列定义中按这种方式使用 REFERENCES 作为注释或提示适用于表 MyISAM BerkeleyDB

6.7. 根据两个键搜索

可以充分利用使用单关键字的 OR 子句 如同 AND 的处理

一个比较灵活的例子是寻找两个通过 OR 组合到一起的关键字

SELECT field1_index, field2_index FROM test_table

WHERE field1_index = '1' OR  field2_index = '1'

还可以使用 UNION 将两个单独的SELECT 语句的输出合成到一起来更有效地解决该问题

每个 SELECT 只搜索一个关键字可以进行优化

SELECT field1_index, field2_index

FROM test_table WHERE field1_index = '1'

UNION

SELECT field1_index, field2_index

FROM test_table WHERE field2_index = '1';

6.8. 根据天计算访问量

下面的例子显示了如何使用位组函数来计算每个月中用户访问网页的天数

CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,

day INT(2) UNSIGNED ZEROFILL);

INSERT INTO t1

VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),

(2000,2,23),(2000,2,23);

示例表中含有代表用户访问网页的年月-日值可以使用以下查询来确定每个月的访问天 数

SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1

GROUP BY year,month;

将返回

 

该查询计算了在表中按年/月组合的不同天数 可以自动去除重复的询问

6.9. 使用 AUTO_INCREMENT

可以通过 AUTO_INCREMENT 属性为新的行产生唯一的标识

CREATE TABLE animals (

id MEDIUMINT NOT NULL AUTO_INCREMENT,

name CHAR(30) NOT NULL,

PRIMARY KEY (id)

);

INSERT INTO animals (name) VALUES

('dog'),('cat'),('penguin'),

('lax'),('whale'),('ostrich');

SELECT * FROM animals;

将返回

+----+---------+

| id | name    |

+----+---------+

|  1 | dog     |

| 2 | cat     |

| 3 | penguin |

|  4 | lax     |

| 5 | whale   |

|  6 | ostrich |

+----+---------+

你可以使用 LAST_INSERT_ID()SQL 函数或 mysql_insert_id() C API 函数来查询最新的  AUTO_INCREMENT 值。这些函数与具体连接有关,因此其返回值不会被其它执行插入功 能的连接影响

注释 对于多行插入LAST_INSERT_ID() mysql_insert_id()从插入的第一行实际返回 AUTO_INCREMENT 关键字。在复制设置中, 通过该函数可以在其它服务器上正确复制多 行插

对于 MyISAM BDB 你可以在第二栏指定AUTO_INCREMENT 以及多列索引此时 AUTO_INCREMENT 列生成的值的计算方法为MAX(auto_increment_column) + 1           WHERE prefix=given-prefix如果想要将数据放入到排序的组中可以使用该方法

CREATE TABLE animals (

grp ENUM('fish','mammal','bird') NOT NULL,

id MEDIUMINT NOT NULL AUTO_INCREMENT,

name CHAR(30) NOT NULL,

PRIMARY KEY (grp,id)

);

INSERT INTO animals (grp,name) VALUES

('mammal','dog'),('mammal','cat'),

('bird','penguin'),('fish','lax'),('mammal','whale '),

('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

将返回

+--------+----+---------+

| grp    | id | name    |

+--------+----+---------+

| fish   |  1 | lax     |

| mammal |  1 | dog     |

| mammal | 2 | cat     |

| mammal |  3 | whale   |

| bird   |  1 | penguin |

| bird   | 2 | ostrich |

+--------+----+---------+

请注意在这种情况下(AUTO_INCREMENT 列是多列索引的一部分), 如果你在任何组中 删除有最大 AUTO_INCREMENT 值的行 将会重新用到 AUTO_INCREMENT 对于  MyISAM 表也如此,对于该表一般不重复使用 AUTO_INCREMENT

如果 AUTO_INCREMENT 列是多索引的一部分MySQL 将使用该索引生成以          AUTO_INCREMENT 列开始的序列值。。例如如果 animals 表含有索引 PRIMARY KEY (grp, id)INDEX(id)MySQL 生成序列值时将忽略 PRIMARY KEY结果是该表包含一 个单个的序列 而不是符合 grp 值的序列

要想以 AUTO_INCREMENT 值开始而不是 1你可以通过 CREATE TABLE  ALTER TABLE 来设置该值如下所示:

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;

7. 孪生项目的查询

3.7.1. 查找所有未分发的孪生项

3.7.2. 显示孪生对状态的表

这个项目是 Institute of Environmental Medicine at Karolinska Institutet Stockholm   the Section on Clinical Research in Aging and Psychology at the University of Southern        California 的合作项目

该项目包括筛选部分即通过电话回访在瑞典超过 65  岁的所有孪生满足某种标准的孪 生进入下一阶段在下一阶段中医生/护士小组将访问想参加的孪生。部分检查包括物理 检查和神经心理检查实验室试验神经成像心理状况评估和家族历史搜集并且 应 根据医疗和环境风险因素来搜集数据

可从以下链接找到孪生研究的更多信息

http://www.mep.ki.se/twinreg/index_en.html

用一个用 Perl  MySQL 编写的 web 接口来管理项目的后面部分

每天晚上所有会谈的数据被移入一个 MySQL 数据库

7.1. 查找所有未分发的孪生项

下列查询用来决定谁进入项目的第二部分

SELECT

CONCAT(p1.id, p1.tvab) + 0 AS tvid,

CONCAT(p1.christian_name, ' ', p1.surname) AS Name,

p1.postal_code AS Code,

p1.city AS City,

pg.abrev AS Area,

IF(td.participation = 'Aborted', 'A', ' ') AS A,

p1.dead AS dead1,

l.event AS event1,

td.suspect AS tsuspect1,

id.suspect AS isuspect1,

td.severe AS tsevere1,

id.severe AS isevere1,

p2.dead AS dead2,

l2.event AS event2,

h2.nurse AS nurse2,

h2.doctor AS doctor2,

td2.suspect AS tsuspect2,

id2.suspect AS isuspect2,

td2.severe AS tsevere2,

id2.severe AS isevere2,

l.finish_date

FROM

twin_project AS tp

/* For Twin 1 */

LEFT JOIN twin_data AS td ON tp.id = td.id

AND tp.tvab = td.tvab

LEFT JOIN informant_data AS id ON tp.id = id.id

AND tp.tvab = id.tvab

LEFT JOIN harmony AS h ON tp.id = h.id

AND tp.tvab = h.tvab

LEFT JOIN lentus AS l ON tp.id = l.id

AND tp.tvab = l.tvab

/* For Twin 2 */

LEFT JOIN twin_data AS td2 ON p2.id = td2.id

AND p2.tvab = td2.tvab

LEFT JOIN informant_data AS id2 ON p2.id = id2.id

AND p2.tvab = id2.tvab

LEFT JOIN harmony AS h2 ON p2.id = h2.id

AND p2.tvab = h2.tvab

LEFT JOIN lentus AS l2 ON p2.id = l2.id

AND p2.tvab = l2.tvab,

person_data AS p1,

person_data AS p2,

postal_groups AS pg

WHERE

/* p1 gets main twin and p2 gets his/her twin. */

/* ptvab is a field inverted from tvab */

p1.id = tp.id AND p1.tvab = tp.tvab AND

p2.id = p1.id AND p2.ptvab = p1.tvab AND

/* Just the screening survey */

tp.survey_no = 5 AND

/* Skip if partner died before 65 but allow emigration (dead=9) */

(p2.dead = 0 OR p2.dead = 9 OR

(p2.dead = 1 AND

(p2.death_date = 0 OR

(((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)

>= 65))))

AND

(

/* Twin is suspect */

(td.future_contact = 'Yes' AND td.suspect = 2) OR

/* Twin is suspect - Informant is Blessed */

(td.future_contact = 'Yes' AND td.suspect = 1

AND id.suspect = 1) OR

/* No twin - Informant is Blessed */

(ISNULL(td.suspect) AND id.suspect = 1

AND id.future_contact = 'Yes') OR

/* Twin broken off - Informant is Blessed */

(td.participation = 'Aborted'

AND id.suspect = 1 AND id.future_contact = 'Yes') OR

/* Twin broken off - No inform - Have partner */

(td.participation = 'Aborted' AND ISNULL(id.suspect)

AND p2.dead = 0))

AND

l.event = 'Finished'

/* Get at area code */

AND SUBSTRING(p1.postal_code, 1, 2) = pg.code

/* Not already distributed */

AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)

/* Has not refused or been aborted */

AND NOT (h.status = 'Refused' OR h.status = 'Aborted'

OR h.status = 'Died' OR h.status = 'Other')

ORDER BY

tvid;

一些解释

·        CONCAT(p1.id, p1.tvab) + 0 AS tvid

我们想要在 id tvab 的连接上以数字顺序排序结果加 0 使得 MySQL 把结果变为一个数

·        id

这标识一对孪生它是所有表中的一个键

·        tvab

这标识孪生中的一个它的值为 1 2

·        ptvab

这是 tvab 的一个逆运算tvab 1它是 2反之亦然它用来保存输入并且使 MySQL 优化查询更容易

这个查询表明 怎样用联结(p1p2)从同一个表中查找表在例子中 这被用来检查孪生 的一个是否在 65 岁前死了如果如此行不返回值

上述所有孪生信息存在于所有表中我们对 id,tvab (所有表 id,ptvab (person_data) 上 采用键以使查询更快

在我们的生产机器上(一台 200MHz UltraSPARC)这个查询返回大约 150-200 行并且时 间不超过一秒

 

7.2. 显示孪生对状态的表

每一次会面以一个称为 event 的状态码结束下面显示的查询被用来显示按事件 组合的所有孪生的表这表明多少对孪生已经完成 多少对的其中之一已完成而 另一个拒绝了等等

SELECT

t1.event,

t2.event,

COUNT(*)

FROM

lentus AS t1,

lentus AS t2,

twin_project AS tp

WHERE

/* We are looking at one pair at a time */

t1.id = tp.id

AND t1.tvab=tp.tvab

AND t1.id = t2.id

/* Just the screening survey */

AND tp.survey_no = 5

/* This makes each pair only appear once */

AND t1.tvab='1' AND t2.tvab='2'

GROUP BY

t1.event, t2.event;

8.  Apache 一起使用 MySQL

还有一些项目 你可以从 MySQL 数据库鉴别用户 并且你还可以将日志文件写入 MySQL 数据库表

你可以将以下内容放到 Apache 配置文件中更改Apache 日志格式使 MySQL 更容易读取

LogFormat \

"\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o

\",   \

\"%U\",\"%{Referer}i\",\"%{User-Agent}i\"" 要想将该格式的日志文件装载到 MySQL你可以使用以下语句:

LOAD DATA INFILE '/local/access_log' INTO TABLE tbl_name

FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'

所创建的表中的列应与写入日志文件的 LogFormat 行对应

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红尘︶炼心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值