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计算每天的访问量
使用auto_increment 3.6.9
3.7使用MySQL和Apache

本章提供了一个入门教程展示了如何使用MySQL的MySQL客户端程序来创建和使用一个简单的数据库。MySQL(有时称为监控终端或者只是显示器)是一个交互式的程序,使您能够连接到MySQL服务器,运行查询,并查看结果。MySQL也可以使用批处理模式:你查询的文件之前,然后告诉MySQL执行该文件的内容。使用方法MySQL这里介绍的是

看到一个选项列表提供的MySQL,调用它的--help选项:

内核>mysql --help

本章假设MySQL安装在你的机器上,MySQL服务器可用,你可以连接。如果这不是真的,接触你的MySQL管理员。(如果是系统管理员,你需要查阅本手册的相关部分,如5章,MySQL服务器管理。)

本章介绍了建立和使用数据库的整个过程。如果你只访问一个现有的数据库有兴趣,你可能想跳过这部分描述如何创建数据库和表,它包含。

由于本章是大自然的教程中,很多细节都是略。参考说明书的相关部分对主题的更多信息在这里。

3.1连接到服务器和从服务器断开

连接到服务器时,你通常需要提供一个MySQL用户名,当你调用MySQL而且,最有可能的是,一个密码。如果服务器运行在一台机器上的其他比你登录,您还需要指定一个主机名。请与您的管理员联系以查明您要使用的连接的连接参数(即,什么主机,使用用户名和密码)。一旦你知道正确的参数,你应该能够连接,这样:

shell> mysql -h host -u user -p
Enter password: ********

hostuser代表主机名在你的MySQL服务器运行的是和你的MySQL帐户的用户名。替代相应的值设置。这个********代表你的密码进入的时候;MySQL显示Enter password:提示

如果成功,你会看到一些入门资料,其次是mysql>提示:

内核>mysql -h host -u user -p输入密码:********欢迎到MySQL监控。命令结束;或g.your MySQL连接ID是25338服务器版:8.0.14-standardtype的帮助;'或' \ H的帮助。型“C”清除缓冲区。MySQL >

这个mysql>提示告诉你MySQL您可以输入SQL语句。

如果你登录到MySQL运行在同一台机器,你可以省略主机,简单地使用下面的:

shell> mysql -u user -p

如果,当您尝试登录,你得到一个错误信息等错误2002(hy000):不能通过插座/甲氧苄啶/ MySQL连接本地MySQL服务器的袜子”(2)。,这意味着MySQL服务器守护进程(UNIX)或服务(Windows)没有运行。咨询管理员或看一段2章,MySQL的安装和升级这是适合您的操作系统。

与其他经常遇到的问题,当试图登录的帮助,看第b.5.2,“常见的错误,当使用mysql程序”

一些MySQL的安装允许用户为匿名连接(未命名)用户的服务器在本地主机上运行。如果这是你的机器的情况下,你应该能够连接到服务器的调用MySQL没有任何选择:

shell> mysql

在你已经连接成功,你可以通过输入断开任何时间QUIT(或Q 0)在mysql>提示:

MySQL的>QUIT拜伊

在UNIX上,还可以断开按控制D.

在下面的章节中大多数示例假设您连接到服务器。他们表示这个由mysql>提示

3.2进入查询

确保您连接到服务器,如在上一节讨论。本身做不选择任何数据库的工作,但这是好的。在这一点上,更重要的是要找出一点关于如何发行查询比跳在创建表格,将数据加载到它们,并从中检索数据。本节描述查询的基本原理,使用多个查询,你可以尝试熟悉如何MySQL作品.

这里是一个简单的查询,要求服务器告诉你它的版本号和当前日期。就如图所示的mysql>提示按回车:

MySQL的>SELECT VERSION(), CURRENT_DATE;----------- -------------- | version() | current_date | ----------- -------------- | 5.8.0-m17 | 2015-12-21 | ----------- -------------- 1行集(0.02秒)MySQL >

这说明了事情的几个查询MySQL

  • 查询通常包括一个SQL语句以分号结尾。(有一些例外情况,分号可以省略。QUIT,前面所提到的,就是其中的一个。我们以后再谈其他。)

  • 当你发出一个查询,MySQL将其发送到执行服务器和显示结果,然后打印一个mysql>提示以表明它是准备另一个查询。

  • MySQL以表格形式显示查询输出(行和列)。第一行包含列标签。该行的查询结果如下。通常情况下,列标签是你从数据库表列取的名字。如果你检索表达式的值,而不是一个表的列(在这个例子中只显示),MySQL标签列使用表达式本身。

  • MySQL显示多少行被返回与查询执行多久了,它给你一个粗略的服务器性能。这些值是不精确,因为他们代表的是挂钟时间(不是CPU或机器时间),因为他们的服务器负载和网络延迟等因素的影响。(为简便起见,本行集线有时是不在本章的剩余的例子所示。)

关键词可以进入任何lettercase。下面的查询是等效的:

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.8.0-m17 |
+-----------+
1 row in set (0.00 sec)

+---------------------+
| NOW()               |
+---------------------+
| 2015-12-21 14:06:10 |
+---------------------+
1 row in set (0.00 sec)

查询不需要给所有在一个单一的线,所以长时间的查询需要几条线也不是问题。MySQL决定你的语句结束寻找终止的分号,不是通过寻找输入行结束。(换句话说,MySQL接受自由格式输入:将输入线但不执行直到它认为分号。)

这里是一个简单的多行语句:

mysql> SELECT
    -> USER()
    -> ,
    -> CURRENT_DATE;
+---------------+--------------+
| USER()        | CURRENT_DATE |
+---------------+--------------+
| jon@localhost | 2015-12-21   |
+---------------+--------------+

在这个例子中,注意及时改变mysql>->你进入一个多行查询后的第一行。这是怎样的MySQL表明它还没有看到一个完整的语句,休息等待。提示是你的朋友,因为它提供了有价值的反馈。如果你使用的反馈,你可以知道什么MySQL是等待

如果你决定你不想执行,你在进入的过程查询,取消输入\c

MySQL的>SELECT->USER()->\cMySQL的>

在这里,太,注意提示。切换回mysql>当你的类型0 C,表明提供反馈MySQL准备一个新的查询

下表显示了每个你看到的提示和总结他们所说的状态MySQL

提示意义
mysql>准备新的查询
->等待下一行多行查询
'>等待下一行,等待一个字符串,开始与一个单一的报价完成('
">等待下一行,等待一个字符串,开始用双引号完成("
`>等待下一行,等待一个标识符,开始与那些完成(`
/*>等待下一行,等待着一个评论,开始完成/*

多行语句通常发生意外时你打算发行一行查询,但忘记结束分号。在这种情况下,MySQL等待更多的输入:

mysql> SELECT USER()
    ->

如果这发生在你的身上(你认为你已经进入了一个声明,但唯一的反应是->提示),最有可能的MySQL等待分号。如果你不注意及时的告诉你,你可能坐在那里一会儿才意识到你需要做什么。输入一个分号来完成报表,并MySQL执行它:

mysql> SELECT USER()
    -> ;
+---------------+
| USER()        |
+---------------+
| jon@localhost |
+---------------+

这个'>“>提示出现在字符串集合(另一种说法是,MySQL是等待一个字符串完成)。在MySQL,你可以写任何字符串包围'字符(例如,'hello'“再见”),和MySQL让你进入跨多行的字符串。当你看到一个'>“>提示,它意味着你已经进入了一个行包含一个字符串,从一个'引号字符,但尚未进入终止的字符串匹配的引号。这通常表明你无意中漏掉了一个引号字符。例如:

mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30;
    '>

如果你进入这个SELECT语句,然后按进入等待结果,什么都没发生。而不是为什么这个查询需要很长的时间,注意所提供的线索'>提示。它告诉你,MySQL希望看到一个未结束的字符串的其余部分。(你在声明中看到错误吗?字符串'Smith失踪的第二单引号。)

在这一点上,你会怎么做?最简单的做法就是取消查询。但是,你不能只是型\c在这种情况下,因为MySQL把它解释为字符串的一部分,它是集。相反,进入闭引号字符(所以MySQL知道你完成了字符串),然后键入\c

MySQL的&#62;SELECT * FROM my_table WHERE name = 'Smith AND age < 30;“&#62;'\cMySQL的&#62;

及时变回mysql>,说明MySQL准备一个新的查询

这个`>提示是类似的“&#62;">提示,但表明你已经开始但尚未完成的那些引用的标识符。

重要的是要知道什么'>“&#62;,和`>提示的意思,因为如果你错误地输入一个未结束的字符串,任何进一步的线似乎忽视了你MySQL该线包括含QUIT。这可能是相当混乱,特别是如果你不知道你要取消当前的查询提供终止报价。

3.3创建和使用数据库

一旦你知道如何输入SQL语句,你可以访问数据库。

假设你在你的家里有几只宠物(动物园)你想跟踪不同类型的关于他们的信息。你可以通过创建表来保存你的数据和装载他们所需的信息。然后你可以从表中检索数据,回答各种关于动物的问题。这一部分向您展示了如何执行以下操作:

  • 创建一个数据库

  • 创建一个表

  • 将数据加载到表

  • 以各种方式从表中检索数据

  • 使用多个表

动物园数据库简单(故意的),但不难想到现实世界中的情况下,类似的数据库可能会使用。例如,一个数据库,这样可以通过农民跟踪家畜使用,或由兽医记录病人的病历。包含一些查询和使用下面的部分样本数据的动物园分布可以从MySQL网站获得。它在压缩是可行的焦油文件和zip格式http://dev.mysql.com DOC

使用SHOW语句来找出目前存在服务器上的数据库:

MySQL的&#62;SHOW DATABASES;---------- |数据库| ---------- | MySQL | |测试| | TMP | ----------

这个mysqldescribes数据库用户的访问权利。《测试数据库通常是作为一个用户尝试做的工作。

由语句显示数据库列表可能会在你的机器上的不同;SHOW DATABASES不显示的数据库,你没有特权,如果你没有SHOW DATABASES特权。看到第13.7.6.14,“显示数据库的语法”

如果test数据库的存在,试图访问它:

MySQL的&#62;USE test数据库的改变

USE,像退出,不需要分号。(你可以终止这样的语句用分号如果你喜欢;它没有伤害的。)USE另一方面,声明太特殊:它必须在一个单一的线。

你可以使用test数据库(如果您有访问它)在下面的例子中,你在数据库中可以被任何人访问还删除创建。出于这个原因,你应该问你的MySQL管理员权限使用你自己的数据库。假设你想打电话给你动物园。管理员需要执行下面的语句:

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,或一些其他的变异。表格名称也是如此。(在Windows的领导下,该限制不适用,虽然你要参考数据库和表使用相同的lettercase在一个给定的查询。然而,由于种种原因,推荐的最佳实践是使用相同的lettercase被用来当数据库被创建。)

笔记

如果你得到一个错误,如错误1044(42000):用户访问被拒绝”弥迦&#39;@&#39;本地主机&#39;数据库&#39;动物园&#39;试图创建数据库时,这意味着,您的用户帐户没有这样做的必要的权限。以管理员或看到讨论这个6.2节,“MySQL的权限系统”

创建一个数据库不选择使用它;你必须做明确。使menagerie目前的数据库,使用此语句:

MySQL的&#62;USE menagerie数据库的改变

你的数据库需要创造,只有一次,但你必须选择使用它时都MySQL会话。你可以通过发行USE表如图所示。或者,你可以选择在命令行调用数据库的时候,你MySQL。只是指定其名称之后,您可能需要提供任何连接参数。例如:

shell> mysql -h host -u user -p menagerie
Enter password: ********
重要

menagerie在命令只显示你的密码。如果你想提供您的密码在命令行-p选择,你必须这样做,没有干预的空间(例如,作为Ppassword不作为,Ppassword)。然而,把你的密码在命令行中是不推荐的,因为这样做使它窥探其他用户登录在你的机器上。

笔记

你可以在任何时间,数据库是目前选择使用SELECTDATABASE()

3.3.2创建表

创建数据库是比较容易的部分,但在这一点上,它是空的,如SHOW TABLES告诉你:

MySQL的&#62;SHOW TABLES;空集(0.001秒)

困难的部分是决定什么是你的数据库的结构应该是:你需要什么,列应该在每个他们表。

你想要一个表包含每个宠物的记录。这可以称为pet表,它应该包含,作为最低限度,每个动物的名称。因为名字本身不是很有趣,桌子应该包含其他的信息。例如,如果你的家族中不止一人养宠物,你可能想列出每个动物的主人。你可能还想记录一些基本的描述性信息,如品种、性别。

怎样的年龄吗?可能是感兴趣的,但它不是存储在数据库中的一个很好的东西。年龄的变化随着时间的推移,这意味着你要经常更新你的记录。相反,它是更好的存储一个固定值,如出生日期。然后,当你需要时,你可以计算为当前日期和出生日期之间的差异。MySQL提供了做日期计算功能,所以这是不难的。存储的出生日期而不是年龄还有其它优点,太:

  • 您可以使用数据库的任务,如生成为即将到来的宠物生日提醒。(如果你认为这类查询是有点傻,注意,这是同一个问题你可能会问在商业数据库中识别客户,他们需要你送出生日祝福在当前一周或一个月,为计算机辅助个人联系。)

  • 你可以计算年龄的关系比其他当前日期的日期。例如,如果你在数据库中存储的死亡日期,你可以很容易地计算出多少岁的宠物是它死了的时候。

你可能认为其他类型的信息,会在是有用的pet表,但那些至今充分:名称、所有者,品种,性别,出生,死亡。

使用CREATE TABLE语句指定你的表格布局:

MySQL的&#62;CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),-&#62;species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);

VARCHAR对于一个好的选择姓名owner,和物种列的列值,因为在长度上的变化。在这些列定义的长度并不一定相同,并且不需要20。你可以挑选任何长度65535无论在你看来,最合理的。如果你犯了一个糟糕的选择,但后来的事实证明,你需要一个较长的领域,MySQL提供了一个ALTER TABLE声明

几种类型的值可以选择动物记录代表性,如'm'“F”,或者'male'“女性”。这是最简单的使用单个字符'm'“F”

使用的DATE为数据类型出生death列是一个相当明显的选择。

一旦你创建了一个表,SHOW TABLES要产生一些输出:

MySQL的&#62;SHOW TABLES;我的意思是,你知道吗?

验证您的表是你期望的方式,使用DESCRIBE声明:

MySQL的&#62;DESCRIBE pet;--------- ------------- ------ ----- --------- ------- |场|型|空|关键|默认|额外| --------- ------------- ------ ----- --------- ------- |名字| varchar(20)|是| |空| | |业主| varchar(20)|是| |空| | |物种| varchar(20)|是| |空| | |性| char(1)|是| |空| | |出生日期是| | | |空| | |死亡日期是| | | |空| | --------- ------------- ------ ----- --------- -------

你可以使用DESCRIBE例如,任何时候,如果你忘记了表中的列的名称或者他们有什么类型的。

关于MySQL数据类型的更多信息,参见11章,数据类型

3.3.3数据加载到表

在创建你的表格,你需要填充它。这个LOAD DATAINSERT声明这是有用的

假设你的宠物的记录可以被描述如下所示。(观察到MySQL的预计日期'YYYY-MM-DD'格式;这可能不同于你所用。)

姓名主人物种性别出生死亡
毛茸茸的哈罗德F1993-02-04
格温M1994-03-17
巴菲哈罗德犬只论坛F1989-05-13
本尼犬只论坛M1990-08-27
鲍尔斯戴安娜犬只论坛M1979-08-311995-07-29
活泼的格温F1998-09-11
惠斯勒格温1997-12-09
苗条的本尼M1996-04-29

因为你是从一个空表,填充它的是创建一个包含你的每一个动物一行文本文件的一个简单的方法,然后加载的文件的内容到表一个声明。

你可以创建一个文本文件pet.txt每行都包含一条记录,用以制表符分隔的值,并给出了在秩序中,列都列在CREATE TABLE声明。缺失值(如性别、死亡日期不明的动物仍然生活),你可以使用无效的价值观。代表这些文本文件中,使用\N(反斜杠,capital-n)。例如,惠斯勒鸟看起来像这样的记录(如数值之间的空格是一个制表符):

Whistler Gwen 1997-12-09鸟\n \n

加载文本文件pet.txt进入宠物表,使用此表:

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

如果你创建和编辑使用Windows文件\r\n作为行结束符,你应该使用这个语句:

MySQL的&#62;LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet-&#62;LINES TERMINATED BY '\r\n';

(在苹果机上运行OS X,你可能会想使用LINES TERMINATED BY '\r'。)

您可以指定列的值显式分离器和结束线标记LOAD DATA声明如果你希望,但默认的制表符和换行符。这些是足够的语句读取文件pet.txt正确

如果语句失败,很可能你的MySQL安装没有默认启用本地文件的能力。看到第6.1.6,“负荷数据的本地“安全问题,关于如何改变这

当你想添加新的记录一次,这INSERT声明是有用的。在其最简单的形式,你供应每列的值,在秩序中,列都列在CREATE TABLE声明。假设戴安娜得到一个新的仓鼠命名马勃您可以添加新的记录使用INSERT这样的陈述:

MySQL的&#62;INSERT INTO pet-&#62;VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);

字符串和日期值指定为字符串来引用。同时,随着INSERT,你可以插入无效的直接代表一个缺失值。你不使用\N喜欢你做的LOAD DATA

从这个例子,你应该能够看到,会有更多的打字参与加载记录最初使用的几个INSERT陈述,而不是一个单一的LOAD DATA声明

3.3.4检索信息从表

这个SELECT语句是用来从表中提取信息。该语句的一般形式为:

选择what_to_selectwhich_table哪里conditions_to_satisfy

what_to_select显示你想看到的。这可以是一个列的列表,或*指示所有列which_table表明表要从中检索数据。这个哪里子句是可选的。如果真的存在,conditions_to_satisfy指定一个或多个条件的行必须满足符合检索。

3.3.4.1选择所有数据

最简单的形式SELECT检索表中的一切:

MySQL的&#62;SELECT * FROM pet;---------- -------- --------- ------ ------------ ------------ |名字|业主|物种|性|出生|死亡| ---------- -------- --------- ------ ------------ ------------ |蓬松|哈罗德|猫| F | 1993-02-04 |空| |爪|格温|猫| M | 1994-03-17 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| |方|本尼|狗| M | 1990-08-27 |空| |库巴|戴安娜|狗| M | 1979-08-31 | 1995-07-29 | |活泼|格温|鸟| F | 1998-09-11 |空| |惠斯勒|格温|鸟|空| 1997-12-09 |空| |苗条|本尼|蛇| M | 1996-04-29 |空| |马勃|戴安娜|仓鼠| F | 1999-03-30 |空| ---------- -------- --------- ------ ------------ ------------

这种形式的SELECT是有用的如果你想回顾你的整个表,例如,当你刚刚加载它与你的初始数据集。例如,你可能会认为Bowser不出生日期似乎很正确。咨询您的原始谱系的论文,你会发现正确的出生年份应该是1989年,不是1979年。

至少有两种方法可以解决这个问题:

  • 编辑文件pet.txt纠正错误,然后空表和加载使用DELETELOAD DATA

    MySQL的&#62;DELETE FROM pet;MySQL的&#62;LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;

    然而,如果你这样做,你也必须进入马勃的记录。

  • 解决只有一个错误的记录UPDATE声明:

    MySQL的&#62;UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';

    这个UPDATE仅仅改变记录的问题,不需要重新加载表。

3.3.4.2选择特定的行

在前一节所示,很容易检索整个表。只是省略WHERE条款从SELECT声明。但是你不想看到整个表,特别是当它变大。相反,你会更有兴趣回答特定的问题,在这种情况下,你指定你想要的信息的一些限制。让我们在选择查询的关于宠物的问题,他们的回答看。

你可以选择从你的表只有特定的行。例如,如果你想验证改变你对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'“库巴”我知道,和等等。the result is the same查询。

你可以指定任何列的条件,不只是name。例如,如果你想知道哪些动物是出生在1998或以后,测试出生专栏

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的&#62;SELECT * FROM pet WHERE species = 'snake' OR species = 'bird';---------- ------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| ---------- ------- --------- ------ ------------ ------- |活泼|格温|鸟| F | 1998-09-11 |空| |惠斯勒|格温|鸟|空| 1997-12-09 |空| |苗条|本尼|蛇| M | 1996-04-29 |空| ---------- ------- --------- ------ ------------ -------

ANDOR可能是intermixed,尽管AND具有更高的优先级OR。如果你使用的运营商,这是一个好主意,用括号明确指出如何条件应分组:

MySQL的&#62;SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm')-&#62;OR (species = 'dog' AND sex = 'f');------- -------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| ------- -------- --------- ------ ------------ ------- |爪|格温|猫| M | 1994-03-17 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| ------- -------- --------- ------ ------------ -------

3.3.4.3选择特定的列

如果你不想在你的桌子上看到整行,只是叫你感兴趣的栏目,以逗号分隔。例如,如果你想知道你的动物出生,选择name出生专栏

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从每个记录栏,有的不止一次出现。为了减少输出,获取每个独特的输出记录一次添加关键词不同的

mysql> SELECT DISTINCT owner FROM pet;
+--------+
| owner  |
+--------+
| Benny  |
| Diane  |
| Gwen   |
| Harold |
+--------+

你可以使用一个WHERE选择行与列选择条款相结合。例如,拿出生日期为狗和猫,用这个查询:

MySQL的&#62;SELECT name, species, birth FROM pet-&#62;WHERE species = 'dog' OR species = 'cat';-------- --------- ------------ |名字|物种|出生| -------- --------- ------------ |蓬松|猫| 1993-02-04 | |爪|猫| 1994-03-17 | |捉鬼|狗| 1989-05-13 | |方|狗| 1990-08-27 | | Bowser |狗| 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像这样:以二元col_name

默认的升序进行排列,最小值。排序(降序)反向顺序,添加DESC关键词要排序的列的名称:

MySQL的&#62;SELECT name, birth FROM pet ORDER BY birth DESC;---------- ------------ |名字|出生| ---------- ------------ |马勃| 1999-03-30 | |活泼| 1998-09-11 | |惠斯勒| 1997-12-09 | |苗条| 1996-04-29 | |爪| 1994-03-17 | |蓬松| 1993-02-04 | |方| 1990-08-27 | | Bowser | 1989-08-31 | |捉鬼| 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关键词只适用于前一列的名字(出生);它不影响species列的排序顺序

3.3.4.1计算日期

MySQL提供了多种功能,您可以使用日期,执行计算,例如,计算年龄或提取部位的日期。

确定多少岁每个宠物,使用TIMESTAMPDIFF()功能。它的参数是你想要的结果表示,单位,和两个日期,以区别。下面的查询显示,每个宠物出生日期,当前日期,并在岁。一个别名age)是用来做最后的输出列标签更有意义。

MySQL的&#62;SELECT name, birth, CURDATE(),-&#62;TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age-&#62;FROM pet;---------- ------------ ------------ ------ |名字|出生| curdate() |年龄| ---------- ------------ ------------ ------ |蓬松| 1993-02-04 | 2003-08-19 | 10 | |爪| 1994-03-17 | 2003-08-19 | 9 | |捉鬼| 1989-05-13 | 2003-08-19 | 14 | |方| 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | |快活| 1998-09-11 | 2003-08-19 | 4 | |惠斯勒| 1997-12-09 | 2003-08-19 | 5 | |苗条| 1996-04-29 | 2003-08-19 | 7 | |马勃| 1999-03-30 | 2003-08-19 | 4 | ---------- ------------ ------------ ------

查询工作,但结果可能是扫描更容易如果行有顺序。这可以通过添加一个ORDER BY name条款按名称排序输出:

MySQL的&#62;SELECT name, birth, CURDATE(),-&#62;TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age-&#62;FROM pet ORDER BY name;---------- ------------ ------------ ------ |名字|出生| curdate() |年龄| ---------- ------------ ------------ ------ | Bowser | 1989-08-31 | 2003-08-19 | 13 | |捉鬼| 1989-05-13 | 2003-08-19 | 14 | |活泼| 1998-09-11 | 2003-08-19 | 4 | |爪| 1994-03-17 | 2003-08-19 | 9 | |方| 1990-08-27 | 2003-08-19 | 12 | |蓬松| 1993-02-04 | 2003-08-19 | 10 | |马勃| 1999-03-30 | 2003-08-19 | 4 | |苗条| 1996-04-29 | 2003-08-19 | 7 | |惠斯勒| 1997-12-09 | 2003-08-19 | 5 | ---------- ------------ ------------ ------

排序输出age而不是姓名,只要使用不同的ORDER BY条款:

MySQL的&#62;SELECT name, birth, CURDATE(),-&#62;TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age-&#62;FROM pet ORDER BY age;---------- ------------ ------------ ------ |名字|出生| curdate() |年龄| ---------- ------------ ------------ ------ |活泼| 1998-09-11 | 2003-08-19 | 4 | |马勃| 1999-03-30 | 2003-08-19 | 4 | |惠斯勒| 1997-12-09 | 2003-08-19 | 5 | |苗条| 1996-04-29 | 2003-08-19 | 7 | |爪| 1994-03-17 | 2003-08-19 | 9 | |蓬松| 1993-02-04 | 2003-08-19 | 10 | |方| 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | |捉鬼| 1989-05-13 | 2003-08-19 | 14 | ---------- ------------ ------------ ------

一个类似的查询可以被用来确定年龄,死亡动物的死亡。你确定哪种动物是通过检查是否death无效的。那么,对于那些非—NULL值,计算之间的差异死亡birth价值观:

MySQL的&#62;SELECT name, birth, death,-&#62;TIMESTAMPDIFF(YEAR,birth,death) AS age-&#62;FROM pet WHERE death IS NOT NULL ORDER BY age;-------- ------------ ------------ ------ |名字|出生|死亡|年龄| -------- ------------ ------------ ------ | Bowser | 1989-08-31 | 1995-07-29 | 5 | -------- ------------ ------------ ------

该查询使用death IS NOT NULL而不是death <> NULL因为NULL是不能用通常的比较运算符比较特殊的价值。这是以后讨论。看到第3.3.4.6,“空值”

如果你想知道哪些动物有生日下个月?这种类型的计算,一年和一天是无关的;你只是想提取该月部分birth专栏MySQL提供了提取部分日期的多种功能,如YEAR()MONTH(),和DAYOFMONTH()MONTH()是适当的功能在这里。看看它是如何工作的,运行一个简单的查询,显示两者的价值出生MONTH(birth)

MySQL的&#62;SELECT name, birth, MONTH(birth) FROM pet;---------- ------------ -------------- |名字| |月出生(出生)| ---------- ------------ -------------- |蓬松| 1993-02-04 | 2 | |爪| 1994-03-17 | 3 | |捉鬼| 1989-05-13 | 5 | |方| 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | |活泼| 1998-09-11 | 9 | |惠斯勒| 1997-12-09 | 12 | |苗条| 1996-04-29 | 4 | |马勃| 1999-03-30 | 3 | ---------- ------------ --------------

发现在即将到来的一个月生日的动物也很简单。假设当月月。然后,月值4你可以寻找动物出生在5月(月)像这样:

mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name  | birth      |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+

有一个小的并发症,如果当前的月份是十二月。你不能只添加一个到月数(12)寻找出生在月的动物十三,因为没有这样的月。相反,你看月生动物(月1

你可以编写查询语句,使其作品无论当前月份是什么,所以你不必使用数量为一个特定的月。DATE_ADD()使您可以添加的时间间隔在一个给定的日期。如果你加入一个月的价值CURDATE(),然后提取月部分MONTH()结果产生,其中月找生日:

MySQL的&#62;SELECT name, birth FROM pet-&#62;WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));

一种不同的方式来完成相同的任务是添加1使用模功能后,当前后获得下一个月(国防部)包月值0如果是目前十二

mysql> SELECT name, birth FROM pet
    -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;

MONTH()返回一个数的关系12。和MOD(something,12)返回一个数的关系11。所以除了必须经过MOD(),否则我们将从十一月(十一)(11

3.3.4.6处理null值

这个NULL值可以是令人惊讶的直到你习惯它。从概念上讲,无效的方法一个失踪的未知值它是从其他价值有所区别对待。

测试NULL,使用IS NULLIS NOT NULL运营商,如下图所示:

MySQL的&#62;SELECT 1 IS NULL, 1 IS NOT NULL;----------- --------------- |是空|不是空| ----------- --------------- | 0 | 1 | ----------- ---------------

你不能使用算术运算符比较运算符如=<,或<>测试无效的。证明自己,尝试以下查询:

mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
|     NULL |      NULL |     NULL |     NULL |
+----------+-----------+----------+----------+

因为任何算法的比较结果NULL是也无效的从这种比较中,你无法获得任何有意义的结果。

在MySQL,0无效的意味着虚假和别的意味着真正的。从布尔操作的默认值是1

这一特殊的治疗NULL所以,在上一节中,有必要确定哪些动物不再活着使用死亡不是空的而不是death <> NULL

NULL值被视为平等的一个

在做一个ORDER BY无效的价值观是第一次提出如果你ORDER BY ... ASC如果你做的一顺序…desc

一个常见的错误,工作时NULL是认为它是不可能插入一个零或空字符串为一个列定义为不为空,但这是没有的情况下。这些其实都是价值观,而NULL方法没有价值你可以利用这个容易测试IS [NOT] NULL如图所示:

MySQL的&#62;SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL;----------- --------------- ------------ ---------------- | 0是空| 0不空|”是无效的|”是无效的| ----------- --------------- ------------ ---------------- | 0 | 1 | 0 | 1 | ----------- --------------- ------------ ----------------

因此,这是完全可能的插入10或空字符串为NOT NULL柱,这些其实都是不为空。看到第b.5.4.3”问题,与空值”

3.3.4.7模式匹配

MySQL提供了标准的SQL模式匹配以及一种基于模式匹配的扩展正则表达式类似于UNIX工具如用不及物动词grep,和SED

可以使用SQL模式匹配_匹配任何单个字符%匹配任意数量的字符(包括零个字符)。在MySQL,SQL是不区分大小写的默认模式。一些例子如下所示。不要使用=<>当你使用SQL模式。使用LIKENOT LIKE比较运算符代替

找到的名字开始b

MySQL的&#62;SELECT * FROM pet WHERE name LIKE 'b%';-------- -------- --------- ------ ------------ ------------ |名字|业主|物种|性|出生|死亡| -------- -------- --------- ------ ------------ ------------ |捉鬼|哈罗德|狗| F | 1989-05-13 |空| |库巴|戴安娜|狗| M | 1989-08-31 | 1995-07-29 | -------- -------- --------- ------ ------------ ------------

找到名字结束fy

MySQL的&#62;SELECT * FROM pet WHERE name LIKE '%fy';-------- -------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| -------- -------- --------- ------ ------------ ------- |蓬松|哈罗德|猫| F | 1993-02-04 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| -------- -------- --------- ------ ------------ -------

找到名字含有w

MySQL的&#62;SELECT * FROM pet WHERE name LIKE '%w%';---------- ------- --------- ------ ------------ ------------ |名字|业主|物种|性|出生|死亡| ---------- ------- --------- ------ ------------ ------------ |爪|格温|猫| M | 1994-03-17 |空| |库巴|戴安娜|狗| M | 1989-08-31 | 1995-07-29 | |惠斯勒|格温|鸟|空| 1997-12-09 |空| ---------- ------- --------- ------ ------------ ------------

找到包含5个字符的名字,使用5的实例_模式特征:

MySQL的&#62;SELECT * FROM pet WHERE name LIKE '_____';------- -------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| ------- -------- --------- ------ ------------ ------- |爪|格温|猫| M | 1994-03-17 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| ------- -------- --------- ------ ------------ -------

模式匹配的MySQL提供的另一种是使用扩展正则表达式。当你测试一个这种类型的模式匹配,使用REGEXP_LIKE()函数(或REGEXPRLIKE运营商,这是同义词REGEXP_LIKE()

下面的列表描述了扩展的正则表达式的一些特点:

  • .匹配任何单个字符

  • 字符类[...]匹配任何字符括号内。例如,[ ABC ]比赛aB,或c。名称字符的范围,使用破折号。[A-Z]匹配任何字母,而[0-9]匹配任何数字

  • *匹配零个或多个实例的东西之前。例如,××匹配任何数量的x字符,[0-9] *匹配任何数量的数字,和.*匹配任何数量的任何东西。

  • 模式的正则表达式匹配成功如果模式匹配的值的任何地方进行测试。(这不同于LIKE模式匹配,成功的模式只有整个价值的比赛。)

  • 锚定一个模式,它必须与被测值的开头或结尾,用^在开始或美元在模式的尽头

演示如何扩展正则表达式的工作,LIKE查询证明以前改写来使用REGEXP_LIKE()

找到的名字开始b,使用^比赛一开始的名称:

mysql> SELECT * FROM pet WHERE REGEXP_LIKE(name, '^b');
+--------+--------+---------+------+------------+------------+
| name   | owner  | species | sex  | birth      | death      |
+--------+--------+---------+------+------------+------------+
| Buffy  | Harold | dog     | f    | 1989-05-13 | NULL       |
| Bowser | Diane  | dog     | m    | 1979-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+

强迫一个正则表达式比较是区分大小写,使用区分大小写的排序规则,或使用BINARY关键词做一个字符串的二进制字符串,或指定C匹配控制字符。每个查询匹配小写b在名字的开头:

SELECT * FROM Pet WHERE regexp_like(名称,“^ B”整理utf8mb4_0900_as_cs);选择*从宠物那里regexp_like(名称、二进制的^ B);选择*从宠物那里regexp_like(名称,“^ B”、“C”);

找到名字结束fy,使用美元匹配名称的结尾:

mysql> SELECT * FROM pet WHERE REGEXP_LIKE(name, '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的&#62;SELECT * FROM pet WHERE REGEXP_LIKE(name, 'w');---------- ------- --------- ------ ------------ ------------ |名字|业主|物种|性|出生|死亡| ---------- ------- --------- ------ ------------ ------------ |爪|格温|猫| M | 1994-03-17 |空| |库巴|戴安娜|狗| M | 1989-08-31 | 1995-07-29 | |惠斯勒|格温|鸟|空| 1997-12-09 |空| ---------- ------- --------- ------ ------------ ------------

因为正则表达式模式匹配,如果它发生在任何一个值,它是没有必要的一个查询中把一个通配符的模式去匹配整个价值为球队将真正的SQL模式。

找到包含五个字符的名字,使用^美元在比赛的开始和结束的名字,和五个实例.在之间:

MySQL的&#62;SELECT * FROM pet WHERE REGEXP_LIKE(name, '^.....$');------- -------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| ------- -------- --------- ------ ------------ ------- |爪|格温|猫| M | 1994-03-17 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| ------- -------- --------- ------ ------------ -------

你也可以写一个查询使用{n}重复—n时报运营商:)

MySQL的&#62;SELECT * FROM pet WHERE REGEXP_LIKE(name, '^.{5}$');------- -------- --------- ------ ------------ ------- |名字|业主|物种|性|出生|死亡| ------- -------- --------- ------ ------------ ------- |爪|格温|猫| M | 1994-03-17 |空| |捉鬼|哈罗德|狗| F | 1989-05-13 |空| ------- -------- --------- ------ ------------ -------

有关正则表达式的语法的更多信息,参见第12.5.2,“正则表达式”

3.3.4.8计数的行

数据库通常被用来回答这个问题,如何往往是一个特定类型的数据表中出现?例如,你可能想知道你有多少宠物,或有多少宠物每个业主都有,或者你可能想在你的动物进行各种普查工作。

计数的动物你的总数是相同的问题多少行在petTable?因为有一个记录每个宠物。COUNT(*)数行数,所以数你的动物查询看起来像这样:

MySQL的&#62;SELECT COUNT(*) FROM pet;---------- |计数(*)| ---------- | 9 | ----------

早些时候,你获取的人谁拥有宠物的名字。你可以使用COUNT()如果你想找出多少宠物每个人:

MySQL的&#62;SELECT owner, COUNT(*) FROM pet GROUP BY owner;-------- ---------- |业主|计数(*)| -------- ---------- |本尼| 2 | |戴安娜| 2 | |格温| 3 | |哈罗德| 2 | -------- ----------

前面的查询使用GROUP BY每个组的所有记录主人。使用COUNT()结合描述你在不同的分组数据是有用的。下面的例子展示了不同的方法来执行动物普查工作。

每种动物的数量:

mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

对动物性:number of

mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex  | COUNT(*) |
+------+----------+
| NULL |        1 |
| f    |        4 |
| m    |        4 |
+------+----------+

(在这个输出,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的&#62;SELECT species, sex, COUNT(*) FROM pet-&#62;WHERE species = 'dog' OR species = 'cat'-&#62;GROUP BY species, sex;--------- ------ ---------- |物种|性|计数(*)| --------- ------ ---------- |猫| F | 1 | |猫| M | 1 | |狗| F | 1 | |狗| M | 2 | --------- ------ ----------

或者,如果你想让动物每性数只动物的性别是已知的:

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 |
+---------+------+----------+

如果你的名字列选择另外的COUNT()价值,一个条款应该是目前的名称相同的列。否则,发生以下情况:

  • 如果ONLY_FULL_GROUP_BYSQL模式启用时,发生了一个错误:

    MySQL的&#62;SET sql_mode = 'ONLY_FULL_GROUP_BY';查询行,0行受影响(0秒)MySQL &#62;SELECT owner, COUNT(*) FROM pet;ERROR 1140 (42000): In aggregated query without GROUP BY, expression#1 of SELECT list contains nonaggregated column 'menagerie.pet.owner';this is incompatible with sql_mode=only_full_group_by
  • 如果ONLY_FULL_GROUP_BY未启用,查询处理的所有行为一个组进行处理,但选择每个指定的列的值是不确定的。服务器是免费的任何行选择的价值:

    MySQL的&#62;SET sql_mode = '';查询行,0行受影响(0秒)MySQL &#62;SELECT owner, COUNT(*) FROM pet;-------- ---------- |业主|计数(*)| -------- ---------- |哈罗德| 8 | -------- ---------- 1行集(0秒)

参见第12.19.3,MySQL处理组”。看到第12.19.1,“总(集团)功能描述有关COUNT(expr)行为和相关的优化

3.3.4.9使用多个表

这个pet表记录你的宠物。如果你想记录它们的其他信息,如他们的生活中的事件像兽医或窝时出生的,你需要另一个表。这张桌子看起来像什么?它需要包含以下信息:

  • 宠物的名字,你知道哪种动物属于每个事件。

  • 一日,你知道事件发生时。

  • 描述事件的字段

  • 一个事件类型字段,如果您希望能够将事件。

给定这些考虑,CREATE TABLE声明为事件表可能看起来像这样:

mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
    -> type VARCHAR(15), remark VARCHAR(255));

pet表,这是最简单的加载初始记录创建一个制表符分隔的文本文件包含以下信息。

姓名日期类型评论
毛茸茸的1995-05-15垃圾4只小猫,3男1女,
巴菲1993-06-23垃圾5只小狗,2男3女,
巴菲1994-06-19垃圾3只小狗,3女
活泼的1999-03-21兽医所需的喙直
苗条的1997-08-03兽医破碎的肋骨
鲍尔斯1991-10-12犬舍
1991-10-12犬舍
1998-08-28生日给他一个新玩具
1998-03-17生日给了他一个新的跳蚤项圈
惠斯勒1998-12-09生日第一个生日

负荷记录这样:

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

基于你从查询得知你已经运行在pet表格,你应该能够执行检索的记录的事件表;原则是相同的。但当是event表本身不足以回答你可能会问?

假设你想找到在这时代每个宠物有窝。前面我们看到如何从两日期计算年龄。母亲的产仔日期在event表,但计算当日你需要她的出生日期她的年龄,这是存储在宠物表这意味着查询要求表:

mysql> SELECT pet.name,
    -> TIMESTAMPDIFF(YEAR,birth,date) AS age,
    -> remark
    -> FROM pet INNER JOIN event
    ->   ON pet.name = event.name
    -> WHERE 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柱。一个查询使用打开(放)条款基于两个表记录匹配name价值观

    查询使用INNER JOIN结合表。一个内部联接证行从表当且仅当表中指定的条件满足出现在结果ON条款.在这个例子中,该打开(放)子句指定的name列在宠物表格必须匹配name列在事件表如果一个名字出现在一个表,而不是其他,该行不会出现在结果因为在条件ON条款没有

  • 因为name列出现在这两个表,你必须具体哪些表你的意思当指柱。这是通过把表名的列的名字了。

你不需要执行一个连接两个不同的表。有时它是加入一个表本身是有用的,如果你想比较记录表中的其他记录在相同的表。例如,找到对繁殖在你的宠物,你可以加入pet表本身产生的男性和女性候选人对像的物种:

MySQL的&#62;SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species-&#62;FROM pet AS p1 INNER JOIN pet AS p2-&#62;  ON p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';-------- ------ -------- ------ --------- |名字|性|名字|性|物种| -------- ------ -------- ------ --------- |蓬松| F |爪| M |猫| |捉鬼| F |方| M |狗| |捉鬼| F |库巴| M |狗| -------- ------ -------- ------ ---------

在该查询中,我们指定指柱和保持直线,审表的每一列参考与表别名。

3.4是对数据库和表的信息

如果你忘记了一个数据库或表的名称,或一个表的结构是什么(例如,它的柱子叫)?MySQL解决这个问题通过几个报表提供有关数据库和表的支持信息。

你以前见过SHOW DATABASES,其中列出了数据库服务器管理。找出哪些数据库的当前选择使用DATABASE()功能:

MySQL的&#62;SELECT DATABASE();| BDE数据库(),| | menagerie | ---------

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

找到默认数据库所包含的表(例如,当你没有对一个表的名称确定),使用该语句:

mysql> SHOW TABLES;
+---------------------+
| Tables_in_menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+

在这个语句产生的输出列的名称总是Tables_in_db_name,在那里db_name是数据库的名称。看到第13.7.6.37,“显示表的语法”为更多的信息

如果你想了解一个表结构的DESCRIBE声明是有用的;它显示每一个表的列信息:

MySQL的&#62;DESCRIBE pet;--------- ------------- ------ ----- --------- ------- |场|型|空|关键|默认|额外| --------- ------------- ------ ----- --------- ------- |名字| varchar(20)|是| |空| | |业主| varchar(20)|是| |空| | |物种| varchar(20)|是| |空| | |性| char(1)|是| |空| | |出生日期是| | | |空| | |死亡日期是| | | |空| | --------- ------------- ------ ----- --------- -------

Field显示列的名称,类型是该列的数据类型,NULL指示列是否可以包含无效的价值观,Key指示列建立索引,并默认指定列的默认值Extra显示列的特殊信息:如果列创建的auto_increment期权的价值将auto_increment而不是空的

DESC是一个简短的形式DESCRIBE。看到第13.8.1“describe语法”为更多的信息

你可以获得CREATE TABLE声明必须创造一个现有的表使用SHOW CREATE TABLE声明。看到第13.7.6.10,“显示创建表的语法

如果你有索引表,SHOW INDEX FROM tbl_name产生的关于他们的信息。看到第13.7.6.22,显示指数的语法”更多关于这个声明

3.5使用mysql的批处理模式

在前面的章节中,你用MySQL交互输入报表和查看结果。你也可以运行MySQL在批处理模式。要做到这一点,把你想运行文件中的陈述,然后告诉MySQL读取输入文件:

shell> mysql < batch-file

如果您正在运行MySQL在Windows和一些特殊字符的文件导致的问题,你可以这样做:

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是交互运行:

+---------+
| species |
+---------+
| bird    |
| cat     |
| dog     |
| hamster |
| snake   |
+---------+

在批处理模式下,输出看起来像这样:

species
bird
cat
dog
hamster
snake

如果你想在批处理模式下的交互式输出格式,使用MySQL - T。回波的输出,执行语句,使用MySQL v

你也可以使用脚本的MySQL提示用source命令或\命令:

mysql> source filename;
mysql> \. filename

看到第4.5.1.5,“执行文本文件中的SQL语句”为更多的信息

常见疑问3.6例

这里是一个例子如何解决MySQL的一些常见问题。

一些例子使用表shop把每个物品的价格(项目编号)的某些贸易商(经销商)。假设每个交易员都有一个固定的价格为每件,然后(文章dealer)是记录的主键

启动命令行工具MySQL选择一个数据库:

shell> mysql your-database-name

(在大多数MySQL的安装,您可以使用指定的数据库test

你可以创建和使用这些语句填充示例表:

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

发布报表后,餐桌上应具备以下内容:

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 |
+---------+--------+-------+

3.6.1最大值为列

最高的项目是什么?

SELECT MAX(article) AS article FROM shop;

+---------+
| article |
+---------+
|       4 |
+---------+

3.6.2行持某一列的最大

任务:找到号码,经销商,和最昂贵的商品价格。

这是很容易做到的子查询:

SELECT article, dealer, price
FROM   shop
WHERE  price=(SELECT MAX(price) FROM shop);

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0004 | D      | 19.95 |
+---------+--------+-------+

其他的解决方案是使用一个LEFT JOIN或所有行降价格排序和使用MySQL特定的只有第一排极限条款:

SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;

SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1;
笔记

如果有一些最昂贵的物品,每一点的价格,LIMIT解决方案将只显示其中的一个。

3.6.3最大柱每组

任务:寻找一条的最高价格。

SELECT article, MAX(price) AS price
FROM   shop
GROUP BY article;

+---------+-------+
| article | price |
+---------+-------+
|    0001 |  3.99 |
|    0002 | 10.99 |
|    0003 |  1.69 |
|    0004 | 19.95 |
+---------+-------+

3.6.4持有某列的分组最大的行

任务:每一篇文章,找到经销商或经销商以最昂贵的价格。

这个问题可以这样解决的子查询:

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0001 | B      |  3.99 |
|    0002 | A      | 10.99 |
|    0003 | C      |  1.69 |
|    0004 | D      | 19.95 |
+---------+--------+-------+

前面的示例使用相关子查询,可以无效(见第13.2.11.7,“相关子查询”)。解决问题的可能性是在使用一个关联子查询FROM条款或左连接

非相关子查询:

SELECT s1.article, dealer, s1.price
FROM shop s1
JOIN (
  SELECT article, MAX(price) AS price
  FROM shop
  GROUP BY article) AS s2
  ON s1.article = s2.article AND s1.price = s2.price;

LEFT JOIN

SELECT s1.article, s1.dealer, s1.priceFROM shop s1LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.priceWHERE s2.article IS NULL;

这个LEFT JOIN在此基础上的作品,当s1.price在它的最大值,没有s2.price一个更大的价值,S2行值将NULL。看到第13.2.10.2,加入“语法”

3.6.5使用用户定义的变量

您可以使用MySQL用户变量,无需存储在临时变量在客户端记住结果。(见4节,“用户定义的变量。)

例如,找到最高和最低的价格可以做文章:

mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
|    0003 | D      |  1.25 |
|    0004 | D      | 19.95 |
+---------+--------+-------+
笔记

它也可以存储一个数据库对象,如表或在用户变量列然后在SQL语句中使用这个变量的名称;然而,这需要一个准备好的声明中使用。看到13.5节,“编写SQL语句语法”为更多的信息

3.6.6使用外键

在MySQL,InnoDB表支持外键约束检查。看到15章,InnoDB存储引擎,和第1.8.2.3,“外键”的区别

外键约束不仅仅是用来连接两个表。存储引擎以外InnoDB,它是可能的定义列时使用推荐信tbl_namecol_name条款,没有实际效果,和只是作为一个备忘录或评论你的专栏你目前的定义是指另一个表中的一列。这是实现使用这个语法时,极为重要:

  • MySQL不执行任何类型的CHECK为了确保col_name真的存在tbl_name(甚至tbl_name自我存在

  • MySQL不执行任何行动tbl_name如删除响应了你所定义的表中的行行为行;换句话说,这个语法没有引起在删除ON UPDATE任何行为。(虽然你可以写一个在删除ON UPDATE条款的一部分推荐信条款,也忽略了。)

  • 此语法创建一个专栏创建任何索引或键

你可以使用一个列创建一个连接列,如下所示:

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 INNER JOIN shirt s
   ON s.owner = p.id
 WHERE p.name LIKE 'Lilliana%'
   AND s.color <> 'white';

+----+-------+--------+-------+
| id | style | color  | owner |
+----+-------+--------+-------+
|  4 | dress | orange |     2 |
|  5 | polo  | red    |     2 |
|  6 | dress | blue   |     2 |
+----+-------+--------+-------+

当用在这时尚的酒店REFERENCES条款中没有输出显示SHOW CREATE TABLEDESCRIBE

SHOW CREATE TABLE shirt\G*************************** 1. row ***************************Table: shirtCreate 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=utf8mb4

使用REFERENCES这样的评论或提醒在一个列定义工作MyISAM

3.6.7搜索两键

一个OR使用一个单一的关键是优化的,为的是处理AND

一个棘手的情况是,在结合两个不同的密钥搜索OR

SELECT field1_index, field2_index FROM test_tableWHERE field1_index = '1' OR  field2_index = '1'

这种情况下的优化。看到部分8.2.1.3,“索引合并优化”

你也可以通过一个有效的解决问题UNION相结合的两个独立输出SELECT站住见第13.2.10.3”联盟,语法”

每个SELECT只有一个键可以搜索优化:

SELECT field1_index, field2_index    FROM test_table WHERE field1_index = '1'UNIONSELECT field1_index, field2_index    FROM test_table WHERE field2_index = '1';

3.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;

它返回:

+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 |    01 |    3 |
| 2000 |    02 |    2 |
+------+-------+------+

查询计算有多少不同的日子每年/月组合出现在餐桌上,随着重复的条目自动去除。

使用auto_increment 3.6.9

这个AUTO_INCREMENT属性可用于生成新行的独特身份:

创建表的动物(ID MEDIUMINT不空auto_increment,名字char(30)不为空,主键(ID));插入动物(名字)值(&#39;dog &#39;),(猫的),(‘企鹅’),(&#39;lax &#39;),(&#39;whale &#39;),(&#39;ostrich &#39;);选择*从动物;

它返回:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

没有值被指定为AUTO_INCREMENT柱,所以MySQL分配序列号自动。你也可以明确指定为列生成序列号,除非NO_AUTO_VALUE_ON_ZEROSQL模式启用。例如:

insert into动物(id,name的值(0),是groundhog);

如果该列声明NOT NULL,还可以分配无效的的列生成序列号。例如:

INSERT INTO animals (id,name) VALUES(NULL,'squirrel');

当你插入任何其他值为AUTO_INCREMENT列,列设置为该值与序列进行复位,以便下次自动生成的值如下顺序从最大的列值。例如:

INSERT INTO animals (id,name) VALUES(100,'rabbit');INSERT INTO animals (id,name) VALUES(NULL,'mouse');SELECT * FROM animals;----- ----------- | ID |名字| ----- ----------- | 1 |狗| | 2 |猫| | 3 |企鹅| | 4 |松懈| | 5 |鲸鱼| | 6 |鸵鸟| | 7 |土拨鼠| | 8 |松鼠| | 100 |兔| | 101 |鼠标| ----- -----------

更新现有的AUTO_INCREMENT列值重置auto_increment序列

你可以检索最新的自动生成AUTO_INCREMENT值与LAST_INSERT_ID()SQL函数或mysql_insert_id()C API函数。这些功能是连接特定的,所以它们的返回值不是由另一个连接,这也是进行插入的影响。

为了用最小的整数数据类型AUTO_INCREMENT柱,足以容纳最大序列值,你需要。当该列的数据类型达到上限,来生成一个序列号的下一个尝试失败。使用无符号属性如果允许一个更大的范围。例如,如果你使用TINYINT,允许的最大序列号是127。为TINYINT UNSIGNED,最大值为255。看到第11.2.1,”Integer Types(精确值)整数int、smallint、TINYINT、MEDIUMINT,bigint”对于所有的整数类型的范围。

笔记

对于多行插入,LAST_INSERT_ID()mysql_insert_id()实际上返回的auto_increment重点从第一插入的行。这使得多行插入被正确复制在复制设置其他服务器。

开始一个AUTO_INCREMENT1以外的值,设定值CREATE TABLEALTER TABLE,像这样:

MySQL的&#62;ALTER TABLE tbl AUTO_INCREMENT = 100;

InnoDB的笔记

有关AUTO_INCREMENT使用特定的InnoDB,看到第15.8.1.5,”auto_increment InnoDB”处理

MyISAM的笔记

  • MyISAM表,您可以指定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)) ENGINE=MyISAM;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表中的索引主键(GRP,ID)INDEX (id),MySQL会忽略primary key生成的序列值。因此,该表将包含一个序列,而不是一个序列的每grp价值

进一步的阅读

更多的信息AUTO_INCREMENT这里是可用的:

3.7使用MySQL和Apache

有程序,让您验证您的用户从一个MySQL数据库,还让你写你的日志文件到一个MySQL表。

您可以更改Apache日志格式,通过MySQL将以下为Apache的配置文件是可读的:

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行写入日志文件