MySQL CRUD 数据表基础操作实战

一、MySQL 命令概述

SQL语言包含四个部分:

  • 数据定义语言(DDL):用于定义和管理数据对象,包括数据库,数据表等。例如:CREATE,DROP,ALTER等。
  • 数据操作语言(DML):用于操作数据库对象中所包含的数据。例如:INSERT,UPDATE,DELETE语句。
  • 数据查询语言(DQL):用于查询数据库对象中所包含的数据,能够进行单表查询,连接查询,嵌套查询,以及集合查询等各种复杂程度不同的数据库查询,并将数据返回客户机中显示。例如:SELETE。
  • 数据控制语言(DCL):是用来管理数据库的语言,包括管理权限及数据更改。例如:GRANT,REVOKE,COMMIT,ROLLBACK等。

1、数据库的连接与关闭命令

mysql –h 服务器主机地址 –u 用户名 –p 用户密码

只有客户机所在的主机被授予权限才能去连接MySQL服务器。

注意:

  1. 每个SQL命令都需要使用分号来完成;
  2. 可以将一行命令拆成多行;
  3. 可以通过c来取消本行命令;
  4. 可以通过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 数据库名称;

注意:

  1. MySQL数据库中命令不区分大小写。
  2. 每创建一个数据库,就会在data目录下创建一个以此数据库名称命名的文件夹。
  3. 在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;

注意事项:     

  1. 表的字段之间要使用逗号隔开;
  2. 建表的最后一句一定不能有逗号;
  3. 表名称和字段名称尽量不要使用MySQL系统的关键字;     
  4. 如果一定要使用关键字,我们可以使用反引号将表名称和字段名称包含起来来进行过滤屏蔽;   
  5. 使用反引号会使建表效率增高; 
  6. 数据表名称和字段名称不能重名;
  7. 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来对字段设置为主键索引。

注意:

  1. 最好为每张表指定一个主键,但不是必须指定;
  2. 一个表只能指定一个主键,而且主键的值不能为空 3.主键可以有多个候选索引(例如NOT NULL,AUTO_INCREMENT);

唯一索引与主键索引一样,都可以防止创建重复的值。但是,不同之处在于,每个数据表中只能有一个主键索引,但可以有多个唯一索引。我们使用关键字UNIQUE对字段定义为唯一索引。

常规索引技术是关系数据查询中最重要的技术,如果要提升数据库的性能,索引优化是首先应该考虑的,因为它能使我们的数据库得到最大性能方面的提升。

常规索引也存在缺点:

  1. 多占用磁盘空间;
  2. 会减慢插入,删除和修改操作;
  3. 需要按照索引列上排序格式执行 创建索引我们可以使用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两种表类型最为重要:

  1. MyISAM数据表类型的特点是成熟、稳定和易于管理;
  2. MyISAM表类型会产生碎片空间,要经常使用OPTIMIZE TABLE命令去清理表空间;
  3. MyISAM不支持事务处理,InnoDB支持;
  4. MyISAM不支持外键,InnoDB支持;
  5. MyISAM表类型的数据表效率更高 6.MyISAM表类型的数据表会产生三个文件,InnoDB表类型表默认只会产生一个文件;

创建表的时候,如果没有明确地指定任何字符集,则新创建数据表的字符集将由MySQL配置文件里charcter-set-server选项的设置决定。

在创建数据表时如果需要指定默认的字符集与之相同,但MySQL客户程序在与服务器通信时使用的字符集,我们需要使用default-character-set选项或通过SQL命令SET NAMES utf8来指定一个字符集为utf8。

创建数据表之前,我们应该注意:

  1. 创建数据库(如已存在则不需要创建);
  2. 选择数据库;
  3. 在该数据库当中创建数据表;

创建数据表需要注意:

  1. 指定数据表的名称(数据表不能重名);
  2. 指定该表的字段名称、字段数据类型、字段索引;
  3. 指定表类型和表默认字符集(可省略);

二、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了。

猜你喜欢

转载自blog.csdn.net/qq_35029061/article/details/128641474