MySQL基础这部分对新手来说,一开始是没有必要接触它的。不过随着使用WordPress的逐步深入,我们会发现有一些操作只有了解掌握了基本的数据库知识才能更好更方便地使用,所以我们接下来将学习一些WordPress能够使用的MySQL数据库的入门基础知识。
15.1 用户
15.1.1
用户登录
跟其他的关系型数据库一样,MySQL本身也有一套权限的管理系统。也就是说,我们可以去创建新的用户,然后给这个用户分配相应的操作权限,比如读取、添加、更新、删除数据等权限。我们也可以让这个用户在指定的数据库上拥有这些权限。
MySQL有一个叫做root的默认用户,它是MySQL上的超级管理员,拥有数据库管理系统上的所有权限。要注意的是,这个root用户跟Linux系统的root用户不是同一个用户。使用root用户的身份登录到MySQL后,我们可以去创建新的用户、可以去为用户分配权限、可以创建数据库并操作数据库。
下面我们来演示如何使用命令行工具来登录到MySQL。Windows系统用户可以借助如Xshell这样的安全终端模拟软件,使用如mysql -h hostname -u
user_name -p这样的命令登录到MySQL。-h参数指的是MySQL服务器的IP地址或者主机名, hostname翻译成中文则是主机名; -u参数指的是连接MySQL服务器的用户名, user_name翻译成中文则是用户名; -p参数指的是连接MySQL服务器的密码。
如果我们想要登录本地主机上面的MySQL,我们可以使用localhost或者127.0.0.1(IPv4)、[::1](IPv6)来代表主机名,或者直接去掉-h参数和主机名;如果我们想要登录到远程主机上的MySQL,我们可以指定一下主机的名称或者IP地址,同时也可以指定想要登录的用户的名称。
使用Xshell登录服务器,由于服务器上已经安装了MySQL,相当于在本地登录,所以我们可以直接使用命令mysql -u root -p。使用后我们输入root用户的密码,如图15-1所示,即可成功登录MySQL。
图15-1 使用默认用户登录数据库并显示当前登录的用户可以管理的数据库
接下来我们可以使用一些命令去做一些事情,比如显示当前登录的用户可以管理的数据库。图15-1所示,我们输入show databases;命令并回车,我们可以看到系统反馈回了所有的数据库的名称信息;这是因为超级管理员拥有最高的权限,可以管理所有的数据库。
注意输入命令完成,记得在末尾加上一个英文输入法下的分号(或者\g),这样的话系统才会执行这条命令。如果没有加上分号就回车,系统会认为我们想继续输入其他命令而不会执行该命令;只有加上了分号(或者\g)这个提示系统命令结束的符号,系统才会执行我们的命令。
15.1.2
创建新用户
root用户是一个万能的用户,为了安全起见我们只能在必要的情况下才去使用它,比如我们添加新的用户或者是创建新的数据库。通常情况下,我们会为Web应用创建一个独立的数据库,并且创建一个拥有这个数据库操作权限的新用户;我们没有必要给这个新用户一个操作其他不相关数据库、添加新的用户等不必要的权限;我们这样做是为了更安全一些,符合最小可用权限的基本原则——只需让新用户拥有能够做事的最少执行动作的权限就足够了。
创建新的用户,我们可以使用create user这个命令。首先我们使用root用户登录服务器,使用命令mysql
-u root -p,然后输入相关的密码登录MySQL。我们可以使用类似create user ‘用户名’@’主机名’
identified by ‘密码’;这样的命令去创建一个新的用户。如图15-2所示,假设我们想在本地主机创建一个名为ipc且密码为ipcdemo!.!的用户,那么我们应输入create
user ‘ipc’@’localhost’ identified by ‘ipcdemo!.!’;这条命令;真正创建密码时,不要像例子这么简单,至少应该输入英文大小写、阿拉伯数字和一些特殊符号等,具体策略可以参考第十七章节。命令输入完成后回车,返回“Query OK”这样的提示,表示我们的这条查询命令成功执行了。
图15-2 为数据库创建新用户
下面我们将试着使用新创建的用户去登录MySQL,输入exit命令并回车,使root用户退出数据库。退出以后,我们使用mysql
-u ipc -p命令,回车后输入相关的密码,如图15-3所示我们成功登录了MySQL。如图15-4所示,我们输入select
current_user();命令,可以看到当前登录的是ipc@localhost;接着我们使用show databases;命令,会发现只有一个名为information_schema的数据库。这是由于我们只创建了新用户,并没有分配相关的权限。
图15-3 使用新用户登录数据库
图15-4 查看当前登录的用户并显示当前登录的用户可以管理的数据库
15.1.3
分配权限
之前我们使用了create user命令为MySQL添加了一个新用户,如果想让这个用户可以做一些事情,需要给它分配一定的权限。权限可以分成下面几个类型:有处理数据库的权限,比如select、insert、update、delete;有影响数据表结构的权限,比如create、alter、index、drop;还有一些管理类型的权限,比如grant、create user等。
要想安全地使用这些权限,我们可以先把它们分成几个层级。我们可以为用户把这些权限分配到全局的范围内,那么这样用户就可以对系统里的所有数据库去执行我们所分配的权限;我们也可以把这些权限分配到指定的数据库、数据表或者数据列上面。通常情况下我们是把权限分配到数据库这个层级上,那么用户就只能在我们指定的数据库里执行我们分配的权限。
分配权限使用的是grant命令,完整的命令应该为grant 权限 on 数据库/数据表 to ‘用户’@’主机名’ [identified by ‘密码’]这样的形式。grant命令的后面就是我们想分配的权限的列表,不同的权限之间我们可以使用英文的逗号来分隔一下;如果想要分配所有的权限,我们可以使用all privileges。这个词翻译成中文后,代表所有的权限; on后面可以指定数据库或数据表,这样做可以使我们分配的权限只应用在我们指定的数据库或数据表上面。在这里我们可以使用.这个占位符去表示所有的数据库。如果只想应用在单独的某一个数据库上面,我们可以使用数据库.数据表的形式把权限应用到所有的数据表上面,所有的数据表可以用来表示,那么相应的占位符应为数据库.; to的后面是用户名和主机名,也就是我们应该分配权限的那个用户;方括号里面的identified
by ‘密码’是一个可选选项,我们可以在这里为用户指定一个高强度的密码。使用grant这个命令分配权限的时候,如果用户还不存在的话,就会创建一个相应的用户。这样的话,我们就可以使用identified
by ‘密码’去为它指定一个登录时使用的密码。
在分配权限的时候,我们还可以去加上一些资源限制的可选选项,这些选项使用with来连接。比如MAX_QUERIES_PER_HOUR,代表着允许用户执行的最大查询语句数量;MAX_CONNECTIONS_PER_HOUR,代表着允许用户连接的最大次数;MAX_UPDATES_PER_HOUR,代表着允许用户执行的最大更新语句数量;MAX_USER_CONNECTIONS,代表着允许用户同时连接服务器的最大数量。上面的这几个选项可以控制用户每小时查询、连接、更新等动作的数量,如果都设置为0的话,就表示我们不进行限制。
我们使用root用户登录到MySQL,然后我们使用grant命令去为新用户ipc分配一些权限。因为我们想为这个新用户分配一些特定的权限,所以我们需要创建一个新的数据库——如图15-5所示,输入create
database ipcdb;命令;然后我们输入grant all privileges on ipcdb.* to
ipc@localhost;命令;接下来,我们输入flush
privileges命令,让这些权限立即生效。如图15-6所示,接下来我们退出MySQL,使用新用户ipc重新登录,输入show
databases;命令,会发现我们拥有数据库权限的数据库多了一个名为ipcdb的数据库。
图15-5 创建新数据库并为新用户分配所有权限且使权限立即生效
图15-6 显示当前登录的用户可以管理的数据库
15.1.4
显示用户列表
我们在数据库系统里面创建的用户和相关的信息,都会在数据库系统的mysql这个数据库的user数据表里面。
比如我们想查看一下在数据库系统里面的所有用户,我们可以这样做——先使用root用户登录MySQL,然后输入select
user from mysql.user; 命令并回车,系统将会反馈会如图15-7所示的结果。
图15-7
查看数据库里面的所有用户
在数据库系统的mysql数据库的user数据表里面,还有一些其他的信息,比如用户的主机名、密码和相关权限等等。如果想要查看user这个数据表里面的所有字段,我们可以输入desc
mysql.user;命令,结果如图15-8所示。如果我们想查看一些特定的字段譬如用户、主机和密码等信息,我们可以使用select
user,host,password from mysql.user;这个命令,由于我们的字段里没有“password”,系统会反馈回错误,所以我们将相关的字段从命令中删除。如图15-9所示,系统反馈回了用户的名字和主机名;如果字段中有“password”,反馈回来的相关的密码将会是经过加密的。
图15-8
查看user数据表里面的所有信息
图15-9
查看user数据表里面的特定字段
15.1.5
显示用户权限
如图15-10所示,查看mysql数据库里面的用户的权限,我们可以使用select user, select_priv from
mysql.user;这个命令; select_priv代表的是用户是否拥有从数据库选择数据的权限。从图15-10可知,root用户拥有这个权限,而其他用户包括我们新创建的用户ipc都没有这个权限。
图15-10
查看mysql数据库里面的用户的权限
使用上面的命令查询出来的权限是全局范围内的权限,而如果我们只想查看用户在某一个特定的数据库上是否拥有权限,可以去看一下mysql数据库里的db数据表。如图15-11所示,我们可以输入select user, db, select_priv
from mysql.db;这个命令,可以得知mysql数据库的db数据表里的用户、拥有权限的特定数据库以及用户是否拥有从数据库选择数据的权限。从图15-11反馈的信息中,我们可以发现我们之前创建的新用户ipc在ipcdb这个数据库里面,确实拥有选择数据的权限。
图15-11
查看用户在某个特定的数据库上是否拥有权限
如果想要查看ipc用户拥有的某些权限的属性,我们可以使用show grants for
ipc@localhost;命令,如图15-12所示。
图15-12
查看用户拥有的某些权限的属性
15.1.6
吊销用户权限
如果想要吊销用户的所有权限或者某几项权限,我们可以使用revoke这个命令。
比如,我们想要吊销ipc这个用户在ipcdb这个数据库里的更新和删除的权限,可以在revoke命令的后面加上要吊销的权限的列表: update代表更新的权限, delete代表删除的权限;如果想要吊销所有的权限,可以使用all
privileges来代表;后面再加上一个on,指定一下具体的数据表——ipcdb.(它代表着ipcdb这个数据库里的所有数据表);from后面就是需要吊销权限的用户ipc。所以,我们应该使用的命令是revoke update, delete on
ipcdb. from ipc@localhost;这个完整的命令,如图15-13所示。。
接下来,我们使用另外一个命令,来查看ipc这个用户在ipcdb这个数据库里面是否还拥有更新和删除的权限。如图15-13所示,我们输入select user, db, update_priv, delete_priv from mysql.db;这个命令——update_priv代表更新的权限; delete_priv代表删除的权限。我们从图15-13中可以得知,ipc用户在ipcdb数据库里的更新和删除权限确实被剥夺了。
图15-13
吊销用户权限
15.1.7
重设密码与删除用户
如图15-14所示,为用户设置密码,我们可以使用set password for
ipc@localhost = password(‘ipcnewdemo!.!’);这条命令。这句命令的意思是为本地数据库的用户ipc设置一个新的密码,新的密码为ipcnewdemo!.!。命令成功执行以后,我们就可以使用新的密码登录了;如果我们想要删除用户ipc,我们可以使用drop
user ipc@localhost;命令;以上的命令执行完毕以后,我们可以使用select
user from mysql.user;这条命令,再查看一下系统里的所有用户,从图15-14中可知,数据库系统里已经没有ipc这个用户了。
图15-14
重设密码与删除用户
15.2 数据库
15.2.1
创建、使用、删除数据库
创建数据库,我们可以使用create database这个命令;create意为创建,database意为数据库。
如果要创建一个新数据库,我们可以在创建数据库命令的后面加上数据库的英文名。假设我们想要创建一个名为ipcdb的数据库,我们可以使用create
database ipcdb;命令;由于之前我们已经创建了同名的数据库,所以如图15-15中所示,系统提示我们无法创建。我们输入show
databases;命令,系统反馈信息告诉我们确实存在这个数据库。
图15-15
尝试创建数据库
如果我们不想看见这个错误提示出现,我们可以使用create database if not exists ipcdb;命令;不过这样做会出现一个警告。如果我们想要了解这个警告的详细信息,可以在登录数据库加上一个“—show-warnings”参数,连在一起的完整命令就是mysql -u root -p
—show-warnings;这样的命令。我们再次使用create database if not exists ipcdb;命令,如图15-16所示,会发现系统反馈回一个代号为1007的错误信息。
图15-16
再次尝试创建数据库并了解错误信息
如果我们想要操作一个数据库,比如说为数据库创建数据表、在数据库里添加(查询/删除)数据等等,需要用use命令切换到该数据库。我们可以输入如use ipcdb;这样的命令,系统会反馈回信息“Database changed”,说明我们正在使用的数据库已经改变到了ipcdb数据库。
如果我们想要删除ipcdb数据库,我们可以使用drop database
ipcdb;命令。命令执行后,我们可以使用show databases;命令,来查看数据库的大致信息——如上图所示,系统反馈回来的数据库中少了ipcdb这个数据库。
图15-17
使用、删除数据库
15.2.2
创建数据表
创建数据表使用的是create table命令(table就是表格的意思);在后面加上要创建的数据表的名字;然后在括号里可以去指定一下数据表里的栏(也就是数据的列,英文是colomun)。不同的栏之间,我们可以使用逗号去分隔一下。接下来我们尝试一下创建数据表的整个过程。
如图15-18所示,我们使用create database ipcdb;命令,创建了一个名为ipcdb的新数据库。然后我们输入use ipcdb;命令,切换到这个新创建的数据库。最后我们输入show tables;命令,查看ipcdb数据库里的所有数据表,从图15-18中可知,现在数据库里没有数据表。
图15-18
创建、使用数据库并查看数据表
接下来,我们尝试给这个数据库添加两条数据表。如图15-19所示,我们使用create table film( film_name
varchar(255), film_date date );命令并回车;这条命令的意思是创建一个名为film的数据表。数据表里有两个数据栏:第一个数据栏叫做film_name,存储的数据类型为字符串(varchar),最大的字符数为255个;第二个数据栏叫做film_date,数据类型的名字为 date。
图15-19
创建、查看数据表
然后我们输入show
tables;命令,查看一下刚刚创建的数据表。如果想查看数据表里的详细信息,我们可以使用describe
film;命令,如图15-19所示,我们看到了我们刚刚创建的两个数据栏的详细信息。
15.2.3
添加数据栏
创建了数据表以后,如果我们想修改这个数据表——比如添加新的数据栏、修改数据栏的名称、删除数据栏或者添加主键等等,这些操作我们都可以使用alter
table这个命令。
怎么为数据表添加新的数据栏呢?我们可以先用alter table,然后加上要更改的数据表的名字,再加上一个add以表示添加,后面接着要添加的数据栏的名字,接着我们可以在后面设置一下新添加的数据栏在数据表中的位置(默认情况下位置会在最后面。如果想出现在最前面,我们可以使用first这个关键词;我们也可以将位置指定在某个数据栏的后面:可以使用after然后再加上这个数据栏的名字)。
如图15-20所示,我们要在刚刚添加的数据栏的前面,添加一个名为id的新数据栏,我们将使用alter table film
add id INT(10) first;这样的命令。id后面的INT表示整数,括号里的10表示其长度为10。接着我们使用describe
film;命令查看film数据表里的数据栏;不出意外的话,我们新添加的数据栏应该在数据栏的最前面,如图15-20所示。
图15-20
添加名为id的新数据栏并查看film数据表里的数据栏
接下来,我们在film_name数据栏的下面,添加一个新的名为film_content、数据类型为文本的数据栏。我们输入alter
table film add film_content TEXT after film_name;命令并回车,接着使用describe
film;命令查看film数据表里的数据栏,结果如图15-21中所示。
图15-21
添加名为film_content的新数据栏并查看film数据表里的数据栏
现在,我们将把之前添加的id数据栏设置成数据表的主键,需要用PRIMARY KEY。我们输入alter
table film add PRIMARY KEY (id);命令,接着使用describe film;命令查看film数据表里的数据栏,结果如图15-22所示。我们可以看到,id数据栏中出现了Key这一栏,其中的值为“PRI”,表示id现在为我们的film这个数据表里的主键了。
图15-22
将之前添加的id数据栏设置成数据表的主键并查看film数据表里的数据栏
15.2.4
修改(删除)数据栏与数据表
我们可以使用alter table命令,对已经存在的数据栏进行更改。比如说更改数据栏的名字、类型,那么我们会用到change这个参数。
如图15-23所示,假设我们要将之前添加的id这个数据栏的名字修改成film_id,我们可以使用alter
table film change id film_id INT(10);这个命令。执行成功后,我们再使用describe
film;命令查看一下这个数据表,从图15-23中可以看到,相关的数据栏的名字已经成功被修改了。
图15-23
修改之前添加的id数据栏的名字并查看film数据表里的数据栏
我们也可以修改数据表的名字,不过这里用到的是rename
to这个参数。如图15-24所示,假设我们想把film数据表的名字改成movie,我们可以使用alter table film
rename to movie;这个命令。然后我们执行show tables;命令,去查看数据库里的数据表,系统反馈的结果如图15-24中所示。
图15-24
修改film数据表的名字并查看数据库里的数据表
我们也可以使用alter table命令删除数据栏,但是需要配合drop去使用。如图15-25所示,比如我们想要删除film_content这个数据栏,我们可以使用alter table movie drop film_content;命令去实现。然后我们再使用describe movie;命令,去查看数据表里的数据栏,系统反馈的结果如图15-25所示。
图15-25
删除film_content数据栏并查看数据表里的数据栏
删除数据表,我们可以使用drop table这个命令,然后在后面加上需要删除的数据表的名字就行了。假设我们要删除movie这个数据表,我们可以使用drop table movie;命令。然后我们执行show tables;命令,去查看数据库里的数据表,不出意外的话系统反馈回“Empty set”,代表我们的命令成功执行了。
15.2.5
重新创建数据库与数据表
在本章节前面的部分中,我们介绍的都是MySQL的DDL语言部分,这部分是定义数据用的。从本章节第三部分开始,我们将会介绍MySQL的DML语言部分(还有一个DCL语言部分):它可以帮助我们往数据表里插入数据,从数据表里选择想要的数据,或者在数据表里更新、删除数据等等。所以在这一小部分文章里,我们将为接下来的部分做一些准备,我们会重新创建一个数据库,并重新创建相关的数据表。
我们先使用root用户身份登录MySQL,如果想即时得知相关的错误信息,我们可以使用mysql -u root -p
—show-warnings;命令登录。如图15-26所示,登录数据库以后,我们使用show databases;命令,我们可以看到我们之前创建的ipcdb这个数据库;然后我们使用drop database ipcdb;命令,删除掉我们自己创建的ipcdb数据库。接着我们马上使用show databases;命令,重新查看相关系统信息,结果如图15-26中所示。
图15-26
删除ipcdb数据库并重新查看数据库
接下来,我们将重新创建一个名为ipcdb并且其字符集里允许中英文同时存在的数据库。我们使用create database ipcdb
charset=utf8;命令,然后使用use ipcdb;命令,切换到新创建的数据库。如图15-27所示。
接着,我们使用create table people( people_id INT(10) unsigned not null
auto_increment, people_name VARCHAR(100), people_birth DATE, people_location
VARCHAR(100), primary key(people_id) ) default charset=utf8;命令,去为数据库创建一个新的名为people的数据表。数据表创建成功后,我们使用describe people;命令,去查看相关数据表的信息,系统反馈信息如图15-27中所示。
图15-27
重新创建数据库与数据表
上面的超长命令中,people_id数据栏的类型为INT,其长度为10, unsingned表示此字段的值只能为正数,接下来的not null表示字段的值不能为空,最后的auto_increment将会使字段的值会依照1→2→3这样的顺序自动增加;接下来的people_name数据栏的类型为VARCHAR,其长度为100;people_name数据栏代表人物的生日,其数据类型为DATE;接下来的数据栏为人物的位置,类型为VARCHAR,其长度为100;接着我们将people_id这个数据栏设置为数据表的主键;最后,我们将数据表的字符集,设置成允许中英文同时存在。
15.3 查询
15.3.1
插入数据
往数据表里插入数据记录,我们可以使用insert命令,其完整命令应为insert into 数据表 (数据栏1, 数据栏2, 数据栏3) values (插入值1, 插入值2, 插入值3);这样的形式。
如图15-28所示,假设我们要插入一个好莱坞演员——丹泽尔·华盛顿的个人基本信息,我们将使用insert into people values
(null, ‘丹泽尔·华盛顿’, ‘1954-12-28’, ‘美国’);命令来达成我们的目的。由于我们是要把数据插入如图15-27中所示的people数据表里的所有数据栏中,所以我们在这个命令里可以省略这部分信息,不过后面要输入的插入值还是得按照数据栏的顺序插入;第一个数据栏是数据表的主键people_id。在之前的命令中,我们使用了auto_increment,它的作用是——如果我们不去指定值的话,系统会依照1→2→3这样的顺序自动增加。由于这样的原因,所以我们在这里使用“null”这个词作为占位符;接下来的三个数据栏的数据,由于其数据类型是文本相关的数据,所以我们在数据外使用单引号。
图15-28
在people数据表中插入新数据
如果我们只是想插入某些数据而不是全部的话,我们可以使用insert into
people (people_name, people_location) values (‘安吉丽娜·朱莉’, ‘美国’);这样的命令,来达到我们的目的——只插入people_name和people_location这两个数据栏的值。
15.3.2
选择数据
如果想从数据库里找出想要的数据,我们可以用select命令,其完整命令应为select 数据栏1, 数据栏2, 数据栏3 from 数据表;这样的形式。
如图15-29所示,我们使用insert into people(people_name,
people_birth, people_location) values (‘马克·沃尔伯格’, ‘1971-06-05’, ‘美国’), (‘布拉德·皮特’, ‘1965-12-18’, ‘美国’), (‘克里斯蒂安·贝尔’, ‘1974-01-30’, ‘英国’), (‘希斯·莱杰’, ‘1979-04-04’, ‘澳大利亚’), (‘凯特·温丝莱特’, ‘1975-10-05’, ‘英国’), (‘莱昂纳多·迪卡普里奥’, ‘1974-11-11’, ‘美国’), (‘休·杰克曼’, ‘1968-10-12’, ‘澳大利亚’), (‘马丁·斯科塞斯’, ‘1942-11-17’, ‘美国’), (‘李安’, ‘1954-10-23’, ‘台湾’);这样的超长命令,提前把演示数据插入到people数据表中。假设我们想要查询出people数据表中所有数据栏的详细信息,我们可以使用select from people;命令,系统反馈回的信息如图15-29所示。
图15-29 在people数据表中插入演示数据并查询数据表中所有数据栏的详细信息
如图15-30所示,如果我们只是想了解这些电影人的名字和生日的详细信息,我们可以使用select
people_name, people_birth from people;命令来达成我们的目的。我们也可以使用where参数去限制一下想要选择的数据的范围,假设我们想要查询所有在美国出生的电影人,我们可以使用select from
people where people_location = ‘美国’;命令,执行以后我们会看到所有在美国出生的电影人的详细信息。
图15-30 查询所有电影人的详细信息、查询所有在美国出生的电影人
对于找到的这些结果,我们可以使用order by参数去进行数据的排序,设置一下排序的方式和条件——比如我们可以按照电影人的出生日期来排序,排序的方式可以是升序(asc)或降序(desc),默认的排序方式为升序。如图15-31所示,我们使用select
- from people order by people_birth desc;命令,对电影人的生日进行降序排列;由于降序排序是按照数字从大到小排列,所以年龄最小的电影人会排在最前面。反之亦然,不过此时使用的应是select
- from people order by people_birth asc;命令。由于安吉丽娜·朱莉的生日为空,此时她是理论上生日数字最小的电影人,所以她会排在最前面,不过事实上生日数字最小的电影人应该是马丁·斯科塞斯。
图15-31 对电影人的生日进行降序排列和升序排列
15.3.3
更新与删除数据
更新数据表里的记录,我们使用的是update命令,其完整命令应为update 数据表名称 set 字段 = ‘值’ where 字段 = 值;这样的形式。
如图15-32所示,我们先使用select from people;命令,把people数据表里的值显示出来。接下来,我们将更新安吉丽娜·朱莉的生日信息,使用update people set people_birth = ‘1975-06-04’ where people_id = 2;命令来达成我们的目的。然后我们再使用select from people;命令,查看people数据表里的信息,我们从图15-32中可以知道安吉丽娜·朱莉的生日信息已经被正确更新。
图15-32 更新安吉丽娜·朱莉的生日信息
删除people数据表里的数据,我们可以使用delete命令。如图15-33所示,假设我们想要删除people_id为6的数据记录,故我们可以把主键的数字6作为删除条件,所以我们将使用delete from people where people_id = 6;命令,把希斯·莱杰的数据记录删除掉。然后我们再使用select * from people;命令,查看people数据表里的信息,我们从图15-33中可以知道希斯·莱杰的相关信息已经被成功删除。
图15-33 删除希斯·莱杰的所有信息
15.3.4
限制结果的数量与偏移
有的时候,我们可能需要对找到的结果的展示数量进行限制。比如在一些Web应用里面会分页显示内容、每一页显示十个内容左右,那么在这种情况下我们就可以使用limit参数去限制一下找到的结果数量,然后使用offset参数去限制一下数据偏移量。
假设我们要找出people数据表里的出生地为美国的电影人,并且我们只需要展示三个结果。如图15-34所示,我们可以使用select * from people where people_location = ‘美国’ limit 3;这个命令去达成这个目的(数字修改成2的话只会展示两个结果)。如果我们允许展示的结果有一定的偏移,我们可以使用offset参数。在一些Web应用分页显示的时候,第一页会显示十个内容、也就是显示查询结果里面的第一个到第十个,这样的话显示第二页内容时应该显示查询结果里面的第十一个到第二十个,这种场景下我们就需要对偏移量进行设置。
图15-34 限制结果的数量与偏移
接下来,我们使用select - from people limit 3 offset 1;命令,随机找出三个电影人并且从第二个开始展示,也就是原本的第二位变成第一位,显示people_id为2、3、4的电影人(offset后的数字修改成2的话会显示people_id为3、4、5的电影人);这里我们也可以换一种命令写法,也就是为limit提供两个条件:一个是数据的偏移量,另一个是限制展示的结果数量。假设我们还是想找出三个电影人并且从第二个结果开始展示,我们可以使用select
- from people limit 1,3;命令。如图15-34所示。
以上三条命令的结果,系统反馈如图15-34中所示。
15.3.5
操作符
在查询的语句中,我们可以使用操作符去进行一些更复杂的事情。其实在本章节前面的部分中,我们早已介绍了等号的作用;除了等号以外,还有许多其他的符号比如大于号“>”、小于号“<”、大于等于号“≥”和小于等于号“≤”可以使用。
假设,我们想要找出所有在1960年1月1号之后出生的电影人,我们可以使用大于号“>”这个操作符,其完整命令应为select from people where people_birth > ‘1960-01-01’;这样的形式,执行完成后我们就可以得到我们想要的结果。
使用逻辑操作符(and、or、not等),我们可以完成更复杂的操作。假设我们想要找出出生日期在1960年1月1号以后且在1970年1月1号以前的电影人,我们可以使用and,其完整命令应为select from people where peoplebirth > ‘1960-01-01’ and people_birth < ‘1970-01-01’;这样的形式。以上两条命令的结果,系统反馈如图15-35所示。
图15-35 出生日期在某个特定时间的电影人
测试一个值是否在一个集合里,我们可以使用in,反之则使用not in。如图15-36所示,假设我们想要找出出生地在美国和英国的电影人,我们可以使用select from people where people_location in (‘美国’, ‘英国’);命令;如果我们想要找出不在美国和英国出生的电影人,则使用not in,所以应该输入select from people where people_location not in (‘美国’, ‘英国’);命令。系统反馈的结果如图15-36所示。
图15-36 出生点在某个特定国家和地区的电影人
我们可以使用like,找出名字中包含某一个字的电影人;在这里我们可以使用两个通配符,百分号“%”表示一个或多个字符,下划线“”表示一个字符。假设我们想要找出名字中包含“李”这个字的电影人,我们可以使用select - from people where people_name like (‘李%’);命令。不出意料之外的话,我们只能找到李安这位电影人。
15.4 关系
15.4.1
为创建关系做准备
在接下来的部分里,我们将会练习使用数据表去创建两个数据表之间的关系。在正式开始以前,我们得准备一下后面会使用到的数据库。
我们先删除之前创建的ipcdb这个数据库——登录数据库,使用drop database ipcdb;命令删除它。然后我们使用show databases;命令,去查看系统里的现有的数据库;如图15-37所示,从系统反馈信息来看,我们可以确定已经删除了ipcdb数据库。
图15-37 删除旧数据库并创建新数据库
接着,我们使用create database ipcdb;命令去创建一个新的名为ipcdb的数据库。然后,输入use
ipcdb;命令,去使用这个新创建的数据库。接下来,我们使用show tables;命令去查看数据库里的数据表,如图15-37所示,系统反馈信息告诉我们里面没有数据表。
接下来,我们将在这个数据库里添加几个数据表,然后在这些数据表里添加一些演示用的数据。我们已经准备好了一个可以直接使用的数据库文件,大家可以在图书附带的资源文件里找到它——其完整的文件名为ipcdb.sql(https://pan.baidu.com/s/1WLEto_RU7WoKFWhmtl8lxg 复制这段内容后打开百度网盘手机App,操作更方便哦)。数据库文件的完整代码块如下。
create table user (
user_id int(10) unsigned not null auto_increment,
user_name varchar(100),
primary key(user_id)
) default charset=utf8;
create table review (
review_id int(10) unsigned not null auto_increment,
review_content text,
review_rate int(10) unsigned,
user_id int(10) unsigned,
film_id int(10) unsigned,
primary key(review_id)
) default charset=utf8;
create table film (
film_id int(10) unsigned not null auto_increment,
film_name varchar(100),
film_box int(10) unsigned,
primary key(film_id)
) default charset=utf8;
create table people (
people_id int(10) unsigned not null auto_increment,
people_name varchar(100),
people_birth date,
people_location varchar(100),
primary key(people_id)
) default charset=utf8;
create table film_people (
film_id int(10) unsigned,
people_id int(10) unsigned,
job varchar(20)
) default charset=utf8;
insert into film(film_id, film_name, film_box) values
(1, '少年派', 124976634),
(2, '雨果', 73820094),
(3, '无间行者', 132373442),
(4, '断背山', 83025853);
insert into user(user_id, user_name) values
(1, '小明'),
(2, '小红'),
(3, '张三');
insert into review(review_id, review_content, review_rate, user_id, film_id) values
(1, '李安导演的少年派,好导演,好故事,推荐看一下', 8, 1, 1),
(2, '今天跟小明一起去看了少年派,电影好看,就是不习惯 3D 眼镜', 9, 2, 1),
(3, '马丁的雨果,很喜欢画面的风格', 8, 1, 2),
(4, '雨果!', 7, 2, 2),
(5, '美国版的无间道,不错', 9, 1, 3),
(6, '看不懂!', 6, 2, 3);
insert into film_people(film_id, people_id, job) values
(1, 11, '导演'),
(2, 10, '导演'),
(3, 8, '演员'),
(3, 10, '导演');
insert into people(people_id, people_name, people_birth, people_location) values
(1, '丹泽尔·华盛顿', '1954-12-28', '美国'),
(2, '安吉丽娜·朱莉', '1975-06-04', '美国'),
(3, '马克·沃尔伯格', '1971-06-05', '美国'),
(4, '布拉德·皮特', '1965-12-18', '美国'),
(5, '克里斯蒂安·贝尔', '1974-01-30', '英国'),
(7, '凯特·温丝莱特', '1975-10-05', '英国'),
(8, '莱昂纳多·迪卡普里奥', '1974-11-11', '美国'),
(9, '休·杰克曼', '1968-10-12', '澳大利亚'),
(10, '马丁·斯科塞斯', '1942-11-17', '美国'),
(11, '李安', '1954-10-23', '台湾');
现在大家看到的上面的代码块,就是我们提前准备好的数据库的结构;和要往数据表里添加的演示数据,如图15-38所示。这些数据都是由SQL语句组成的,稍后我们将把它导入到数据库里面。
这些演示数据的最开始的部分,就是我们最先创建的数据表。这里我们创建了一个名为user的数据表,在这个数据表里存储的是Web应用的用户的相关信息:它里面有两个字段,一个是user_id,另外一个是user_name。
在数据的第二部分,我们创建了一个名为review的数据表,顾名思义,放的是评论相关的内容。这个数据表里有五个字段:一个是review_id,第二个是review_content(用来存储用户的评论内容),第三个是review_rate(用来存储用户评分),第四个是user_id(与user数据表里的用户一一对应),最后一个是film_id(这个值与下面的film_id的值是一一对应的)。
在数据的第三部分,我们创建了一个名为film的数据表。这个数据表里有三个字段:第一个是film_id,第二个是film_name,最后一个则是film_box(代表着电影的票房)。
数据的第四部分,即people数据表里,则存放着电影人相关的信息。people_id代表电影人的id, people_name代表电影人的名字, people_birth代表电影人的生日,people_location则代表电影人的出生地。
演示数据最后的一部分,我们创建了一个名为film_people的数据表,它里面存储的是电影和电影人的关系。数据表里有三个字段:film_id、people_id、job(代表电影人在电影里出任的角色,比如导演、编剧、演员等)。
图15-38 需要添加的演示数据
在这些数据之后的内容,则是我们要插入到上面的数据表里的演示数据,如图15-38所示。接下来,我们要把这个ipcdb.sql文件导入到ipcdb数据库中;我们可以使用数据库管理软件phpMyAdmin来达成我们的目的。之前使用OneinStack配置网站应用运行环境时,我们已经安装了一个phpMyAdmin。我们在浏览器地址栏中输入如127.0.0.1/phpMyAdmin/这样的地址并回车,登陆到phpMyAdmin的登录界面(127.0.0.1请替换成服务器的公网IP地址,并且可以将phpMyAdmin更改成其他任何你喜欢的英文名字)。如图15-39所示,我们使用root身份登录到phpMyAdmin后,点击选择左侧的ipcdb数据库,然后点击导入,在计算机中选择我们准备好的ipcdb.sql文件,最后点击执行。执行结果如图15-40所示,从图中可以看出,我们准备的演示数据已成功导入到了ipcdb数据库。
图15-39 把ipcdb.sql文件导入到数据库中
图15-40 准备的演示数据成功导入到数据库
15.4.2
关联
我们可以利用数据表与数据表之间的关系,去重新关联组合出不同特点的信息。
如图15-41所示,假设我们想把用户和评论者两个数据表组合在一起,然后找出所有的用户所撰写的全部评论,而且找到的结果里面要包含用户的名字以及相对应的评论内容。我们可以使用select user_name,
review_content from user, review where review.user_id = user.user_id;命令去达成我们的目的。
因为user_name是user数据表里的、review_content是review数据表里的,所以后面的from后加上user和review。然后我们用where参数设置一下条件,这个条件是把user和review数据表关联组合在一起的非常重要的关键点:使review数据表里的user_id等价于user数据表里的user_id。从图15-41中我们可以看到,user_name已经和review_content关联在一起。关联以后,这个表里面有两栏内容,分别是来自用户表里的用户名和评论表里的内容。由于在实际应用中,用户极有可能会更改自己的用户名和其他相关的个人信息,所以我们在设计数据表结构时,不直接把用户名放在评论表里面,而是单独使用id号 。
图15-41 交叉关联用户名和评论内容
上面的命令中from的后面的user和review这两个要关联的表的中间使用了一个逗号“,”,其功能相当于交叉关联(CROSS
JOIN)。不过我们也可以用内部关联(INNER JOIN)的方法来输出相同的内容,演示结果如图15-42所示,所以我们刚才使用的命令也可以改成select
user_name, review_content from user inner join review on review.user_id =
user.user_id;这样的形式。代码的作用,也就是相当于在内部比较一下user_name和review_content的共同点(前面的代码相当于在外部比较一下交叉点,用数学概念里的维恩图来说就是交集)。
图15-42 交叉关联和内部关联
在这条命令的后面,我们可以继续使用where参数去设置其他的条件,比如说我们想要找出user_id为1的用户的所有评论,我们可以继续在命令后面加上where user.user_id = 1,所以完整的命令就是像select
user_name, review_content from user inner join review on review.user_id =
user.user_id where user.user_id = 1;这样。我们找到的评论如图15-43所示。
图15-43 在命令后面使用where参数设置其他的条件
15.4.3
左关联
除了内部关联(INNER JOIN),还有一些其他的关联方法比如左关联(LEFT JOIN)。既然它是关联的一种方法,那么它也会按照两个数据表的共同点来匹配,把它们关联在一起。就算是不匹配,它也会把左边的数据表的记录显示出来。
假设我们依然想把用户和评论这两个数据表的记录关联在一起,但是我们这次想要找出用户表里的所有用户名,不管某一个用户有没有写过评论;如果真的没有写过的话,其对应的评论栏里的数据将会为NULL!如果写过评论的话,其对应的评论栏里的数据就会是以前写的评论内容!
我们使用select user_name, review_content from user left join review on
review.user_id = user.user_id;命令,达成我们上面的目标。如图15-44所示,我们的命令把用户和评论这两个数据表,按照用户的id这个共同点进行了匹配,然后再把它们关联在了一起!
图15-44 左关联数据表
既然有左关联(LEFT JOIN),那么肯定也有右关联(RIGHT JOIN),不过用了右关联以后,就会使用上面的右边的数据表为主去进行关联!
15.4.4
统计、分组、平均
使用MySQL提供的一些函数,我们可以去统计、求和、求平均数、找出最大(小)值等等。
如果我们想要统计一下结果的数量,那么可以使用count这个函数。如图15-45所示,假设我们想要统计review数据表里的记录数量,输入select count(review_id) from
review;命令后回车执行,就会得到我们想要的结果。
图15-45 统计、分组结果的数量
如果我们想要找出每一部电影的评论数量,则可以使用group by去进行分组:按照评论数据表里面的film_id分一下组。如图15-45所示,我们输入select film_id,
count(review_id) from review group by film_id;命令并回车执行,从图15-45所示的系统反馈可以知道,这三部电影里的每一部电影的评论都是两条!
接下来,我们尝试一下求平均数用的函数avg。如图15-46所示,假设我们想要计算一下每部电影评分的平均分,输入select film_id,
avg(review_rate) from review group by film_id;命令后马上回车执行,系统反馈回的结果就是每一部电影的平均分。配合关联系统还可以显示出相关电影的名字:我们可以使用select review.film_id,
film.film_name, avg(review_rate) from review, film where review.film_id =
film.film_id group by review.film_id;命令,从图15-45所示的反馈信息中,我们知道了刚才每一部电影的评分所对应的电影名字!
图15-46 平均结果的数量
15.4.5
三个表的关联
**
使用关联,我们可以做一些更复杂的查询。接下来,我们将尝试着把电影、电影人、电影和电影人之间关系的这几个数据表关联在一起。
电影这个数据表里放的是与电影有关的内容——比如电影人的名称、电影票房等;电影人这个数据表里面是所有电影从业人员的信息——比如电影人的名字、出生地、出生日期等;电影和电影人之间关系的数据表里面,放的是电影的id和与电影相关的电影人的id以及一些其他的相关信息。
我们要做的就是利用电影和电影人这两个数据表里的内容,把电影和电影人这两个数据表关联在一起。关联以后,保留电影的名字和与电影相关的所有电影人,以及出演角色信息等。如图15-47所示,我们输入select
film_name, people_name, job from film, people, film_people where film_people.film_id
= film.film_id and film_people.people_id = people.people_id;命令并回车执行;如果要找出某一部电影的所有工作人员,我们只需要在前面的基础上加上and film_name = ‘电影名字’即可。假设我们想要找出电影《无间行者》的所有工作人员,那么我们应该使用select
film_name, people_name, job from film, people, film_people where
film_people.film_id = film.film_id and film_people.people_id = people.people_id
and film_name = ‘无间行者’;这个命令,找出的结果如图15-47所示;如果我们想要找出某一个电影人参与过的所有电影作品,我们则使用select
film_name, people_name, job from film, people, film_people where
film_people.film_id = film.film_id and film_people.people_id = people.people_id
and people_name like ‘马丁%’;这个命令,也就是把and
film_name = ‘电影名字’替换成and people_name
like ‘人名%’。
图15-47 三个表的关联
接下来,我们将统计每个导演的制作过的所有电影的总票房,并把这些数据按照降序排列。如图15-48所示,我们可以使用select sum(film_box) as total_box,
people_name from film, people, film_people where film_people.film_id =
film.film_id and film_people.people_id = people.people_id and job = ‘导演’ group
by people_name order by total_box desc;命令达成我们的目的。其中,sum的作用是统计求和;total_box是为了方便统计电影总票房而自行创造出来的,相关的数据库中并不存在这个参数。具体的电影总票房如图15-48所示。
图15-48 统计电影总票房并降序排列