一、MySQL 命令概述
SQL语言包含四个部分:
- 数据定义语言(DDL):用于定义和管理数据对象,包括数据库,数据表等。例如:CREATE,DROP,ALTER等。
- 数据操作语言(DML):用于操作数据库对象中所包含的数据。例如:INSERT,UPDATE,DELETE语句。
- 数据查询语言(DQL):用于查询数据库对象中所包含的数据,能够进行单表查询,连接查询,嵌套查询,以及集合查询等各种复杂程度不同的数据库查询,并将数据返回客户机中显示。例如:SELETE。
- 数据控制语言(DCL):是用来管理数据库的语言,包括管理权限及数据更改。例如:GRANT,REVOKE,COMMIT,ROLLBACK等。
1、数据库的连接与关闭命令
mysql –h 服务器主机地址 –u 用户名 –p 用户密码
只有客户机所在的主机被授予权限才能去连接MySQL服务器。
注意:
- 每个SQL命令都需要使用分号来完成;
- 可以将一行命令拆成多行;
- 可以通过c来取消本行命令;
- 可以通过q、exit、ctrl+c或者quit来退出当前客户端;
2、Mysql中的快捷键
我们可以使用help命令来查询快捷键:
- 将查询后的数据立起来:G;
- 取消当前未完成的操作:c;
- 退出当前客户端:q;
- 显示当前服务器状态:s;
- 显示帮助信息:h(同help命令);
- 更改执行符:d;
3、数据库操作
建立数据库命令:
CREATE DATABASE [IF NOT EXISTS] 数据库名称;
删除数据库:
DROP DATABASE [IF EXISTS] 数据库名称;
显示当前数据库服务器下的所有数据库列表:
SHOW DATABASES;
选择数据库:
USE 数据库名称;
注意:
- MySQL数据库中命令不区分大小写。
- 每创建一个数据库,就会在data目录下创建一个以此数据库名称命名的文件夹。
- 在Windows下,数据库名称也是不区分大小写的,但在Linux下,数据库名称严格区分大小写。
4、数据表操作
简单的创建数据表语法:
CREATE TABLE [IF NOT EXISTS] 表名称(字段1信息,字段2信息…字段N信息)[ENGINE=MyISAM DEFAULT CHARSET=UTF8];
删除数据表:
DROP TABLE [IF EXISTS] 数据表名称;
修改表结构:
ALTER TABLE 数据表名称 相关操作;
我们可以对表进行修改字段,添加字段,删除字段,添加索引,删除索引,更改表名称,更改字段名称,更改auto_increment属性的初始值等。
插入数据:
INSERT INTO 表名称[(字段名称)] VALUE(前面字段对应的值);
查询数据:
SELECT 字段名称1,字段名称2,… FROM 表名称
更改数据:
UPDATE 数据表 set 字段名称=新修改的值 [WHERE 条件]
删除数据:
DELETE FROM 表名称 [WHERE 条件]
下面我们正式建一个表:
中文名 |
字段名 |
数据类型 |
属性 |
索引 |
用户编号 |
id |
INT |
UNSIGNED NOT NULL AUTO_INCREMENT |
主键 |
用户名称 |
username |
VARCHAR(50) |
NOT NULL |
普通 |
口令 |
userpass |
VARCHAR(50) |
NOT NULL |
普通 |
联系电话 |
telno |
VARCHAR(20) |
NOT NULL |
唯一 |
性别 |
sex |
ENUM(‘男’,’女’) |
NOT NULL DEFAULT ‘男’ |
|
出生日期 |
birthday |
DATE |
NOT NULL DEFAULT ‘0000-00-00’ |
下面是建表语句:
set character_set_server=utf8; #将Mysql服务的字符集改为utf8,这样待会建的库和表就都是utf8的字符
create database test; #建库
use test #使用库才能建表
CREATE TABLE IF NOT EXISTS `users`(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`userpass` VARCHAR(50) NOT NULL,
`telno` VARCHAR(20) NOT NULL UNIQUE, # unique表示建立唯一键
`sex` ENUM(‘男’,’女’) NOT NULL DEFAULT ‘男’,
`birthday` DATE NOT NULL DEFAULT ‘0000-00-00’,
PRIMARY KEY(`id`), #建立唯一键
INDEX username_index(`username`), #建立普通索引
INDEX userpass_index(`userpass`) #建立普通索引
)ENGINE=MyISAM;
注意事项:
- 表的字段之间要使用逗号隔开;
- 建表的最后一句一定不能有逗号;
- 表名称和字段名称尽量不要使用MySQL系统的关键字;
- 如果一定要使用关键字,我们可以使用反引号将表名称和字段名称包含起来来进行过滤屏蔽;
- 使用反引号会使建表效率增高;
- 数据表名称和字段名称不能重名;
- AUTO_INCREMENT属性必须依附于主键索引或唯一索引;
修改字段:
我们使用change或者是modify关键字。
ALTER TABLE `uses` CHANGE `username` `uname` VARCHAR(32) NOT NULL; ALTER TABLE `users` MODIFY `username` VARCHAR(32) NOT NULL;
由上例可以发现: change可以改变字段名称,而modify不可以。
添加字段:
我们使用add关键字。
ALTER TABLE `uses` ADD `tname` VARCHAR(32) NOT NULL;
这样我们就会新增一个tname字段。
删除字段:
我们使用drop关键字。
ALTER TABLE `users` DROP `tname`;
这样我们会删除tname字段。
更改表名称:
我们使用rename关键字。
ALTER TABLE 旧表名 RENAME AS 新表名
将旧表名更改为新表名。
更改AUTO_INCREMENT初始值:
ALTER TABLE 表名称 AUTO_INCREMENT=1
将AUTO_INCREMENT的初始值设置为1。
5、创建新用户并授权
GRANT 权限 ON 数据库.数据表 TO 用户名@登录主机 IDENTIFIED BY “密码”
例如: 添加一个新用户名为lijie,密码为字符串“jiege”。让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先要以root用户登录,然后输入以下命令:
GRANT SELECT,INSERT,UPDATE,DELETE ON *.* TO lisi@”%” IDENTIFIED BY “123”
6、索引操作
在MySQL中,主要有四类索引: 主键索引(PRIMARY KEY) 唯一索引(UNIQUE) 常规索引(INDEX) 全文索引(FULLTEXT)。
主键索引是关系数据库中最常见的索引类型,主要作用是确定数据表里一条特定的数据记录的位置。我们可以在字段后添加PRIMARY KEY来对字段设置为主键索引。
注意:
- 最好为每张表指定一个主键,但不是必须指定;
- 一个表只能指定一个主键,而且主键的值不能为空 3.主键可以有多个候选索引(例如NOT NULL,AUTO_INCREMENT);
唯一索引与主键索引一样,都可以防止创建重复的值。但是,不同之处在于,每个数据表中只能有一个主键索引,但可以有多个唯一索引。我们使用关键字UNIQUE对字段定义为唯一索引。
常规索引技术是关系数据查询中最重要的技术,如果要提升数据库的性能,索引优化是首先应该考虑的,因为它能使我们的数据库得到最大性能方面的提升。
常规索引也存在缺点:
- 多占用磁盘空间;
- 会减慢插入,删除和修改操作;
- 需要按照索引列上排序格式执行 创建索引我们可以使用INDEX和KEY关键字随表一同创建;
全文索引在MySQL中是一个FULLTEXT类型索引,但FULLTEXT索引只能用于MyISAM表,并且只可以在CHAR、VARCHAR或TEXT类型的列上创建,也允许创建在一个或多个数据列上。
但是FULLTEXT是不支持中文全文索引的,所以我们将来会使用效率更高的全文索引引擎Sphinx。
1. 添加和删除索引
我们使用add关键字添加索引:
ALTER TABLE `uses` ADD INDEX/UNIQUE/PRIMARY KEY(字段名称)
这样会在该字段上建立索引(普通索引,唯一索引,主键索引)。
删除索引:
ALTER TABLE `users` DROP 索引名称;
这样我们会删除这个索引,我们可以使用show indexes from 表名查看当前表索引。
2. 数据表的类型和储存位置
MySQL支持MyISAM、InnoDB、HEAP、BOB、ARCHIVE、CSV等多种数据表类型,在创建一个新MySQL数据表时,可以为它设置一个类型。
MyISAM和InnoDB两种表类型最为重要:
- MyISAM数据表类型的特点是成熟、稳定和易于管理;
- MyISAM表类型会产生碎片空间,要经常使用OPTIMIZE TABLE命令去清理表空间;
- MyISAM不支持事务处理,InnoDB支持;
- MyISAM不支持外键,InnoDB支持;
- MyISAM表类型的数据表效率更高 6.MyISAM表类型的数据表会产生三个文件,InnoDB表类型表默认只会产生一个文件;
创建表的时候,如果没有明确地指定任何字符集,则新创建数据表的字符集将由MySQL配置文件里charcter-set-server选项的设置决定。
在创建数据表时如果需要指定默认的字符集与之相同,但MySQL客户程序在与服务器通信时使用的字符集,我们需要使用default-character-set选项或通过SQL命令SET NAMES utf8来指定一个字符集为utf8。
创建数据表之前,我们应该注意:
- 创建数据库(如已存在则不需要创建);
- 选择数据库;
- 在该数据库当中创建数据表;
创建数据表需要注意:
- 指定数据表的名称(数据表不能重名);
- 指定该表的字段名称、字段数据类型、字段索引;
- 指定表类型和表默认字符集(可省略);
二、MySQL 数据表设计
数据表是数据库中的基本对象元素,以记录(行)和字段(列)组成的二维结构用于存储数据。数据表由表结构和表内容两部分组成,先建立表结构,然后才能输入数据。
数据表结构设计主要包括字段名称、字段类型和字段属性的设置。 通常情况下,同一个数据库中可以有多个数据表,但表名必须是唯一的,表中每一条记录描述了一个相关信息的集合,每一个字段必须为唯一的,每个字段都需要指定数据类型。
1、字段类型
1. 数字类型
数据列类型 |
存储空间 |
说明 |
取值范围 |
TINYINT |
1字节 |
非常小的整数 |
带符号值:-128~127 无符号值:0~255 |
SMALLINT |
2字节 |
较小的整数 |
带符号值:-32768~32767 无符号值:0~65535 |
MEDIUMINT |
3字节 |
中等大小的整数 |
带符号值:-8388608~8388607 无符号值:0~16777215 |
INT |
4字节 |
标准整数 |
带符号值:-2147483648~2147483647 无符号值:0~4294967295 |
BIGINT |
8字节 |
大整数 |
带符号值:-263~263-1 无符号值:0~264-1 |
FLOAT |
4或8字节 |
单精度浮点数 |
最小非零值:+- 1.175494351E-38 最大非零值:+- 3.402823466E+38 |
DOUBLE | 8字节 | 双精度浮点数 | 最小非零值:+- 2.225073E-308 最大非零值:+- 1.797693E+308 |
DECIMAL | 自定义 | 以字符串形式表示的浮点数 | 取决于存储单元字节数 |
整型注意事项: INT(3)、SMALLINT(3)等整型后面的数字不会影响数值的存储范围,只会影响显示 整型后面的数字只有配合零填充的时候才有实际意义,整型后面的数字可以省略。
浮点型注意事项: 浮点型后面的数字会将存入的数字四舍五入,例如:把一个1.234存入FLOAT(6,1)数据列中,结果是1.2,6代表显示长度,1代表小数位长度,会四舍五入。
2. 字符串类型
数据列类型 |
存储空间 |
说明 |
取值范围 |
CHAR[(M)] |
M字节 |
定长字符串 |
M字节 |
VARCHAR[(M)] |
L+1字节 |
可变字符串 |
M字节 |
TINYBLOB,TINYTEXT |
L+1字节 |
非常小的BLOB(二进制大对象)和文本串 |
28-1字节 |
BLOB,TEXT |
L+2字节 |
小BLOB和文本串 |
216-1字节 |
MEDIUMBLOB, MEDIUMTEXT |
L+3字节 |
中等的BLOB和文本串 |
224-1字节 |
LONGBLOB, LONGTEXT |
L+4字节 |
大BLOB和文本串 |
232-1字节 |
ENUM(‘value1’,’value2’…) |
1或2字节 |
枚举:可赋予某个枚举成员 |
65535个成员 |
SET(‘value1’,‘value2’…) |
1,2,3,4或8字节 |
集合:可赋予多个集合成员 |
64个成员 |
字符串类型注意事项:
- CHAR和VARCHAR类型的长度范围都在0~255之间;
- 在使用CHAR和VARCHAR类型时,当我们传入的实际的值的长度大于指定的长度,字符串会被截取至指定长度在使用CHAR类型时,如果我们传入的值的长度小于指定长度,实际长度会使用空格补至指定长度;
- 在使用VARCHAR类型时,如果我们传入的值的长度小于指定长度,实际长度即为传入字符串的长度,不会使用空格填补;
- CHAR要比VARCHAR效率更高,当占用空间较大;
- BLOB和TEXT类型是可以存放任意大数据的数据类型;
- BLOB区分大小写,TEXT不区分大小写;
- ENUM和SET类型是特殊的的串类型,其列值必须从固定的串集中选择;
- ENUM只能选择其中一个值,SET可以选择多个值;
3. 日期和时间类型
数据列类型 |
存储空间 |
说明 |
取值范围 |
DATE |
3 字节 |
“YYYY-MM-DD”格式表示的日期值 |
1000-01-01~9999-12-31 |
TIME |
3 字节 |
“hh:mm:ss”格式表示的时间值 |
-838:59:59-838:59:59 |
DATETIME |
8 字节 |
“YYYY-MM-DD hh:mm:ss”格式 |
1000-01-01 00:00:00~9999-12-31 |
TIMESTAMP |
4 字节 |
“YYYYMMDDhhmmss”格式表示的时间戳 |
19700101000000-2037年的某个时刻 |
YEAR |
1 字节 |
“YYYY”格式的年份值 |
1901~2155 |
存储日期时,我们可以使用整型 int 来进行存储时间戳,这样做便于我们进行日期的计算。
NULL值注意事项:
- NULL意味着“没有值”或“未知值”;
- 可以测试某个值是否为NULL;
- 不能对NULL值进行算术计算;
- 对NULL值进行算术运算,其结果还是NULL;
- 0或NULL都意味着假,其余值都意味着真;
和PHP类似,在MySQL的表达式中,如果某个数据值的类型与上下文所要求的类型不相符,MySQL则会根据将要进行的操作自动地对数据值进行类型转换。
2、字段属性
1. UNSIGNED
只能用于设置数值类型,不允许出现负数,最大存储长度会增加一倍。
2. ZEROFILL
只能用于设置数值类型,在数值之前会自动用0补齐不足的位数。
3. AUTO_INCREMENT
用于设置字段的自动增长属性,每增加一条记录,该字段的值会自动加1。
NULL和NOT NULL,默认为NULL,即插入值时没有在此字段插入值,默认为NULL值,如果指定了NOT NULL,则必须在插入值时在此字段填入值。
4. DEFAULT
可以通过此属性来指定一个默认值,如果没有在此列添加值,那么默认添加此值。
三、数据表CRUD操作
1、插入数据
插入数据是向已经存在的数据表中添加一条新的记录,应该使用INSERT INTO语句。
格式:
INSERT INTO 表名 [(字段名1,字段名2,…字段名n)] VALUES(‘值1’,‘值2’,…,’值n’);
或者:
INSERT INTO 表名 [(字段名1,字段名2,…字段名n)] VALUES(‘值1’,‘值2’,…,‘值n’),VALUES(‘值1’,‘值2’,…,’值n’);
2、更新数据
SQL语句可以使用UPDATE语句对表中的一列或多列数据进行修改,必须指定需要修改的字段,并且需要赋予的新值。还要给出必要的WHERE子句指定要更新的数据行。
格式:
UPDATE 表名 SET 字段名=表达式 [,…][WHERE 条件] [ORDER BY 字段][LIMIT 行数]
3、删除数据
DELETE语句用来删除数据表中的一条或多条数据记录。
格式:
DELETE FROM 表名 [WHERE 条件][ORDER BY 字段][LIMIT 行数]
4、查询数据
查询语句可以完成简单的单表查询,也可以完成复杂的多表查询和嵌套查询。SELECT语句主要用于数据的查询检索,是SQL语言的核心,在SQL语言中SELECT语句的使用频率是最高的。
格式:
SELECT [ALL|DISTINCT]{*|table.*|[table.]field1[AS alias1][,[table.]field2[AS alias2][,…]]}FROM 表名 [WHERE子句] [GROUP BY..][HAVING..][ORDER BY..][LIMIT count];
最简单的查询语句是使用SELECT语句检索记录的特定字段,多个字段可以用逗号分隔,例如:
SELECT username,password FROM user;
也可以使用*从表中检索出所有字段,使用“SELECT *”主要是针对用户的书写方便而言的。
如果一张表当中的数据多大几百万,就意味着资源的浪费和漫长的查询等待,所以实际应用时要尽量避免使用它,而把查询的列名准确地列出来,也可以按自己指定的列顺序输出。
如果想为返回的列取一个新的标题,以及经过对字段的计算或总结之后,产生了一个新的值,希望把它放到一个新的列里显示,则用AS保留。
例如:在上例的输出结果中使用中文字段名,可以在MySQL控制台中输入的命令如下所示:
SELECT username as ‘用户名’ FROM user;
定义别名时一定要使用单引号引起来,其中AS关键字是可选的,在原字段名和别名之间使用一个空格即可。
SELECT username ‘用户名’ FROM user;
如果在使用SELECT语句返回的记录结果中包含重复的记录,可以使用DISTINCT关键字取消重复的数据,只返回一个。
另外,要注意DISTINCT关键字的作用是整个查询的列表,而不是单独的一列。
DISTINCT会消耗一定的服务器资源,如果不指定,会默认使用ALL关键字作为检索模式。
SELECT DISTINCT gid FROM user_group;
在SQL中的表达式用法和PHP程序相似,主要包括算术表达式、逻辑表达式,以及使用SQL函数表达式等。 例如:
SELECT version(),1.23*10;
在SELECT语句中,可以使用WHERE子句指定搜索条件,实现从数据表中检索出符合条件的记录。其中,搜索条件可以由一个或多个逻辑表达式组成,这些表达式指定关于某一记录是真或假的条件。在WHERE子句中,可以通过逻辑操作符和比较操作符指定基本的表达式条件。
逻辑操作符:
操作符 |
语法 |
描述 |
AND 或 && |
a AND b 或 a && b |
逻辑与,若两个操作数同时为真,则为真 |
OR 或 || |
a OR b 或 a||b |
逻辑或,只要有一个操作数为真,则为真 |
XOR |
a XOR b |
逻辑异或,若有且仅有一个操作数为真,则为真 |
NOT 或 ! |
NOT a 或 !a |
逻辑非,若操作数为假,则为真 |
比较操作符:
数据列类型 |
存储空间 说明 |
取值范围 |
= |
a=b |
若操作数a与操作数b相等,则为真 |
<=> |
a<=>b |
若a与b相等,则为真,可以用于NULL值比较 |
!=或<> |
a!=b或a<>b |
若操作数a与b不相等,为真 |
< |
a |
若操作数a小于b,为真 |
<= |
a<=b |
若操作数a大于b,为真 |
> |
a>b |
若操作数a大于b,为真 |
>= |
a>=b |
若操作数a大于等于b,为真 |
IS NULL |
a IS NULL |
若操作数a为NULL,为真 |
IS NOT NULL |
a IS NOT NULL |
若操作数a不为NULL,为真 |
BETWEEN |
a BETWEEN b AND c |
若a在b和c之间,为真 |
比较操作符:
数据列类型 |
存储空间 说明 |
取值范围 |
NOT BETWEEN |
a NOT BETWEEN b AND c |
若操作数a不在b和c之间,为真 |
LIKE |
a LIKE b |
SQL模式匹配,若a匹配b,为真 |
NOT LIKE |
a NOT LIKE b |
SQL模式匹配,若a不匹配b,则为真 |
IN |
a IN (b1,b2….) |
若a等于b1,b2,b3,…中的某一个,则为真 |
在构造搜索条件时,要注意只能对数值数据类型的记录进行算术运算,并且只能在相同的数据类型之间进行记录的比较。
1. 根据空值(NULL)确定检索条件
空值只能定义在允许NULL字段中出现,NULL值是特殊的值,代表“无值”,与零值(0)和空字符串('')都不相同。当在不支持默认值的字段中未输入值,或在字段中显式的设置为空,就会出现空值,但不能用处理已知值的方式来处理NULL。
为了进行NULL值的搜索,必须采用特殊的语法。如果要检索NULL值,必须使用IS NULL和IS NOT NULL关键字。
2. 使用BETWEEN AND进行范围比较查询
如果需要对某个字段通过范围的值进行比较查询,可以使用BETWEEN AND关键字实现,其中AND是多重条件符号,比较时也包括边界条件。也可以使用“>=”和“<=”完成同样的功能。
3. 使用IN进行范围比对查询
在WHERE子句中,使用IN关键字并在后面的括号“()”中提供一个值的列表,以供与相应的字段进行比较。该列表中至少应该存在一个值,如果有多个值可以使用逗号“,”分隔。
4. 使用LIKE进行模糊查询
在SELECT语句的WHERE子句中,可以使用LIKE关键字对数据表中的记录进行模糊查询,将查询结果锁定在一个范围内。在查询条件中通常会与“_”和“%”两个通配符一起使用,可以实现复杂的检索查询。这两个通配符的含义分别如下:
百分号“%”:表示0个或任意多个字符。
下画线“_”:表示单个的任意一个字符。 相反的,不匹配我们使用NOT LIKE。
5. 使用ORDER BY对查询结果排序
使用SELECT语句获取数据表中的数据时,返回的记录一般是无规则排列的,有可能每次获取的查询记录截然不同。为了使用检索的结果方便阅读,可以在SELECT语句中使用ORDER BY子句,对检索的结果进行排序。 ORDER BY后面可以接一列或多列用于排序的字段,并且使用DESC或ASC关键字设计字段排序的方式。
默认情况下按照升序排列,即使用ASC关键字。否则要按照降序排列,必须使用DESC关键字。ORDER BY子句可以和SELECT语句中的其他子句一起使用,但在子查询中不能有ORDER BY子句,因为ORDER BY子句只能对最终查询结果排序。
6. 使用LIMIT限定结果行数
如果在数据表中的记录数非常多,一次从表中返回大量的记录不仅检索的速度慢,用户阅读也很不方便。所以在通过SELECT语句检索时,使用LIMIT子句一次取少量的记录,而用分页的方式继续阅读后面的数据。
LIMIT子句也可以和其他的SELECT子句一起使用,它可以指定两个参数,分别用以设置返回记录的起始位置,和返回记录的数量。
LIMIT子句也可以只使用一个参数,表示从开头位置,即偏移量为0的位置返回指定数量的记录,在上例中使用的“LIMIT 0, 5”等价于“LIMIT 5”。
7. 使用统计函数
在数据库系统中提供了一系列的内置统计函数,在SQL查询中使用这些统计函数可以更有效地处理数据。这些统计函数把存储在数据库中的数据,描述为一个整体而不是一行行孤立的记录。
统计函数 |
描 述 |
COUNT() |
返回满足SELECT语句中指定条件的记录数,例如,COUNT(*)返回找到的记录行数 |
SUM() |
通常为数值字段或表达列作统计,返回一列的总和 |
AVG() |
通常为数值字段或表达列作统计,返回一列的平均值 |
MAX() |
可以为数值字段、字符字段或表达列作统计,返回一列中最大的值 |
MIN() |
可以为数值字段、字符字段或表达列统计,返回一列中最小的值 |
这些函数通常用在SELECT子句中,作为结果数据集的字段返回的结果。在SELECT语句的SELECT子句中使用函数的语法如下:
SELECT 函数名(列名1 或*),...函数名(列名n) FROM 表名; #使用统计函数
8. 使用GROUP BY对查询结果分组
前面使用统计函数返回的是所有记录的统计结果,如果要对数据进行分组统计,就需要使用GROUP BY子句。这将可以允许用户在对数据进行分类的基础上,进行再查询。GROUP BY子句将表按列值分组,列的值相同的分为一组。如果GROUP BY后面有多个列名,则先按第一个列名分组,再在每组中按第二个列名分组。
需要注意的是,在GROUP BY子句中不支持对字段分配别名,也不支持任何使用了统计函数的集合列。 在完成数据结果的分组查询和统计后,还可以使用HAVING子句来对查询的结果,进行进一步的筛选。 在SELECT语句的子句中:WHERE子句选择所需要的行;GROUP BY子句进行了必要的分组整理;而HAVING子句对最后的分组结果进行了重新筛选。
9. 查询优化
EXPLAIN语句是检测索引和查询能否良好匹配的简便方法。
如果想检测:
SELECT * FROM table WHERE a>’0’ AND b<’1’ ORDER BY c;
这条语句的性能可以:
EXPLAIN SELECT * FROM table WHERE a>’0’ AND b<’1’ ORDER BY c;
10. 多表查询(连接查询)
多表查询给用户带来很大的灵活性,可以在任何时候增加新的数据类型,为不同实体创建新的表,然后通过连接进行查询。
11. 嵌套查询(子查询)
这种查询是在一个SELECT语句的WHERE子句中,包含另一个SELECT语句,也可以称为子查询。在子查询中只能返回一列,并将形成的结果又作为父查询的条件,在主句中进行进一步查询。 SQL语言允许多层嵌套查询,即一个子查中还可以有其他子查询。
嵌套查询的求解方法是由里向外处理,即每个子查询都是在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
四、数据库与表备份及导入
1、数据库的导出
导出一个库:
mysqldump -uroot -p 库名 > 库名.sql
导出后的文件会放在当前目录。
导出一个表:
mysqldump -uroot -p 库名 表名 > 表名.sql
导出数据库中的表结构:
mysqldump -uroot -p -d 库名 > 库名.sql
导出数据库中某个表的表结构:
mysqldump -uroot -p 库名 -d 表名 > 表名.sql
2、数据库的导入
如果导入数据库或者数据表的时候,mysql中不存在这个库,就需要先建立一个库,然后使用这个库,然后用source命令导入数据
create database 库名
source 数据库或数据表文件的绝对路径 (如 source d:/wamp/www/user.sql)
mysql设置或者重设密码:
set password for root@localhost = password('密码内容');
3、部分备份
使用select into outfile和mysqldump进行部分备份,select into outfile可以用于有条件的或者部分导出一张表或者多张表的数据到本地。
语法如下:
SELECT ... INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
[export_options]
export_options:
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
例如:
select uid,nickname,realname,mobile,idcard from m order by m.uid desc into outfile '/var/www/api/public/a/download/m.txt' fields terminated by ',' optionally enclosed by '\"' escaped by '\"' lines terminated by '\r\n'
意思是将数据导出到m.txt,每个字段之间要用“,”分隔,每一行数据要以"\r\n"换行。
导出的数据是没有表头的。
导入的时候使用LOAD命令:
LOAD DATA INFILE '/tmp/fi.txt' INTO TABLE test.fii FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
在导出的时候可能会报错:
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
这是因为mysql服务开启的时候为了安全考虑,使用了--secure-file-priv这个参数,此时用 select into outfile导出的文件只能导出到指定的目录,这个目录可以通过下面命令查看:
SELECT @@global.secure_file_priv;
+---------------------------+
| @@global.secure_file_priv |
+---------------------------+
| D:\wamp64\tmp\ |
+---------------------------+
所以使用 select into outfile 和 load infile 都限定了只能导出和导入这个目录下的数据。
但是 select into outfile 对于那种有text类型的文章表而言不太友好,因为文章内容就包含了很多\r\n的换行符。
除了select into outfile之外,还可以mysqldump加上 -w(--where)的方式进行部分复制。
# --databases 导出多个库
mysqldump -uroot -p --databases db1 db2 > mysqldump.sql
# 导出一个库的多个表
mysqldump -uroot -p db1 t1 t2 > mysqldump.sql
# --ignore-table导出时忽略某个表
mysqldump -uroot -p test --ignore-table=test.t1 --ignore-table=test.t2 > /backup/mysqldump/test2.db
# --all-databases 导出所有库
mysqldump -uroot -p --all-databases
# --where导出特定条件的数据
mysqldump -uroot -p --host=localhost --all-databases --where=” user=’root’”
五、MySQL 权限和安全
1、MySQL访问权限系统
MySQL权限系统的主要功能是证实连接到一台给定主机的用户,并且赋予该用户在数据库上的各种权限,一般生产环境中的程序账号只需要SELECT、INSERT、UPDATE和DELETE权限即可
MySQL将验证用户的3项 信息:用户名、密码、主机来源。
权限可以分为两类:系统权限和对象选项。 系统权限允许执行一些特定的功能,如关闭数据库、终止进程、显示数据库列表、查看当前执行的查询等。对象权限是指 对一些特殊的对象(表、列、视图、数据库)的访问权限,例如是否允许访问某张表,是否允许在某个库中创建表。
一般不允许直接更改MySQL的权限表,而是通过GRANT和REVOKE语句进行权限的赋予和收回,这也是更安全可靠的办法。
GRANT和REVOKE语句允许系统管理员创建MySQL用户账户、授予权限和撤销权限。授予的权限可以分为多个级别:服务器级别(全局)、数据库级别、表级别、列级别、子程序级别。撤销权限即回收已经存在的权限。
GRANT [privileges] ON [objects] TO [user]
GRANT [privileges] ON [objects] TO [user] IDENTIFIED BY [password]
REVOKE [privileges] ON [objects] FROM [user]
MySQL为有SUPER权限的用户专门保留了一个额外的连接,因此即使是所有的普通连接都被占用,MySQLroot用户仍可以登录并检查服务器的活动。
如果想要限制单个账号允许的连接数量,可以通过设置max_user_connections变量来完成。
当在GRANT语句中指定数据库名称时,允许使用“_”和“%”通配符。这意味着,如果想要使用“_”字符作为一个数据库名称的一部分,则应该在GRANT语句中指定它为“\_”,例如,“GRANT…ON‘foo\_bar’.*TO…。”
SHOW TABLES命令不会显示用户没有权限访问的表。
2、常用的权限
SHOW PRIVILEGES命令可以显示MySQL所支持的权限,如下是一些常用的权限。
SELECT、INSERT、UPDATE和DELETE权限允许用户在一个数据库现有的表上实施读取、插入、更新和删除记录的操作。这也是一般程序账号所需要的权限。
SHOW VIEW权限允许用户查看已经创建了的视图。
ALTER权限允许用户使用ALTERTABLE命令来修改现有数据表的结构。
CREATE和DROP权限允许用户创建新的数据库和表,或者删除现存的数据库和表。生产环境中一般不赋予程序账号DROP的权限。GRANT权限允许用户把自己拥有的权限授予其他的用户。·FILE权限允许被授予该权限的用户都能读或写MySQL服务器能读写的任何文件。
SHUTDOWN权限允许用户使用SHUTDOWN命令关掉服务器。可以创建一个用户专门用来关闭服务器。
PROCESS权限允许用户使用PROCESSLIST命令显示在服务器内执行的进程的信息;使用KILL命令终止服务器进程。用户总是能显示或终止自己的进程,但是,显示或终止其他用户启动的进程则需要PROCESS权限。一些监控工具需要PROCESS权 限查看正在执行的命令。
显示某个用户的权限的命令如下:
SHOW GRANTS FOR username@'ip_range';
如:
show grants for root@localhost;
show grants for [email protected]
show grants 只能查看一个用户的权限。
如果想查看所有用户可以:
use mysql
select host,user from user;
不过这个只能看到哪个用户的那个ip可以连接该台服务器,看不到权限。
赋予某个用户对库db1进行SELECT、INSERT、UPDATE和DELETE的权限的命令如下。
GRANT SELECT,INSERT,UPDATE,DELETE ON db1.* TO username@'10.%' IDENTIFIED BY 'your_password';
又如:
grant all privileges on art1.* to zbp@"127.0.0.1" identified by "123456"; # 赋予zbp用户在本机上对art1所有表的所有权限; on *.* 表示所有库的所有表; 如果允许zbp在所有的ip上远程连接该数据库则 zbp@"%"
在mysql中127.0.0.1和localhost不同,mysql -uroot -p 默认的主机是 localhost ; 所以如果想用刚刚的zbp登陆就要 mysql -h127.0.0.1 -uzbp -p 才可以。
如果相对赋予权限的用户修改密码,只需重新赋予一次权限即可。
如需撤销权限可以这样:
revoke all privileges on art1.* from [email protected];
一定要制定好要撤销的权限,库表、用户和主机名缺一不可,最好赋予权限的时候怎么写,撤销的时候原封不动的复制,如果忘记了可以用 show grants 命令查看。
当撤消了zbp用户的权限之后,在查看zbp的权限:
show grants for [email protected]
+-----------------------------------------+
| Grants for [email protected] |
+-----------------------------------------+
| GRANT USAGE ON *.* TO 'zbp'@'127.0.0.1' |
+-----------------------------------------+
发现还有一个USAGE权限,这是zbp的登陆权限还留着。
revoke usage on *.* from [email protected] ;
发现还是没法删除这个权限。
其实删掉这个用户即可:
drop user [email protected]; # 删除用户除了要指定用户名还要指定ip,而且ip在赋予权限的时候怎么设,删的时候就要怎么写
下面是具体的mysql远程连接的例子:
两台服务器:192.0.0.10和192.0.0.11,现在192.0.0.11要远程连接到192.0.0.10。
在 192.0.0.10设置权限:
grant all privileges on *.* to zbp@"192.0.0.11" identified by "123456"; # 可以执行flush privileges 刷新一下权限
然后在192.0.0.11就可以连接 192.0.0.10了:
mysql -h 192.0.0.10 -u zbp -p 123456
那么接下来就是说一下一系列无法远程连接的状况:
Can't connect to MySQL server on 'xxx' (111)
这种情况的话需要在被连接的服务器 192.0.0.10 的数据库配置文件 /etc/my.cnf 找到 bind-address = 127.0.0.1 在他后面加一个ip 192.0.0.11允许这台服务器连接。
bind-address = 127.0.0.1 192.0.0.11
如果不知道自己的mysql配置文件在哪里可以这样:
which mysqld #得到mysqld命令的绝对路径,我这里是/usr/sbin/mysqld
/usr/sbin/mysqld --verbose --help |grep -A 1 'Default options'
就会显示mysql的配置文件位置,会显示多个,所以要一个个找。
如果在/etc/my.cnf找不到这句,可能在my.cnf所引入的其他配置文件中里,例如 my.cnf中有一句!includedir /etc/my.cnf.d ,意思是引入这个目录下所有的配置文件,所以可以在这个目录下的配置文件下找找看。
如果找不到,那么可以直接自己在my.cnf加一句bind-address:
Can't connect to MySQL server on 'xxx' (110)
110的情况是防火墙的原因,此时在 192.0.0.11 和 192.0.0.10 都关掉防火墙,然后重启一下mysql服务:
systemctl stop firewalld
如果还是不行,那么很可能是因为你的服务器是云服务器,此时要登陆云服务器后台开启3306端口对外开放才行。
最后如果被连接的服务器撤消了[email protected]的权限之后,192.0.0.11依旧可以通过zbp用户连接到192.0.0.10的mysql服务器。但权限已经没了,无法查看或者操作远程服务器的表和数据,可以在192.0.0.10删掉zbp用户,这样.11就无法连接到.10了。