MySQL
安装数据库
Mysql5.7地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip
如果安装过Mysql过程中,出错了
sc delete mysql 【删除已经安装好的mysql服务】
1.解压
2.添加环境变量,在Path环境变量增加mysql的安装目录\bin目录 【例如: D:\java\mysql\mysql-5.7.19-winx64\bin】
3.在 安装 目录下创建my.ini文件,需要我们自己创建
[client]
port=3306
default-character-set=utf8
[mysqld]
# 设置为自己MYSQL的安装目录
basedir=D:\java\mysql\mysql-5.7.19-winx64\
# 设置为MYSQL的数据目录
datadir=D:\java\mysql\mysql-5.7.19-winx64\data\
port=3306
character_set_server=utf8
#跳过安全检查,将其注销后,需要正确密码登录
skip-grant-tables
4.使用管理员身份打开cmd,并切换到bin目录下,执行下面的语句
mysqld -install
5.初始化数据库,执行下面语句
mysqld --initialize-insecure --user=mysql
6.数据库启动
启动
net start mysql
停止
net stop mysql
7.进入mysql管理终端,执行如下指令
mysql -u root -p
当前root密码为空
8.修改root用户密码
use mysql;
update user set authentication_string=password('AAAA') where user='root' and Host='localhost';
上面的语句就是修改root用户的密码为AAAA
刷新权限: flush privileges;
退出: quit
9.修改my.ini的最后一行,将其注释,再次进入就会进行权限验证了
#skip-grant-tables
10.重新启动mysql
net stop mysql
net start mysql
- 再次进入Mysql, 输入正确的用户名和密码
mysql -u root -p
密码正确,进入mysql
使用命令行连接数据库
mysql -h 主机IP -P 端口 -u 用户名 -p密码
第一个-P是大写
第二个-p,后面不加空格,后面如果没有写密码,回车会要求输入密码
如果没有写-h主机,默认就是本机
如果没有写-P端口,默认就是3306
数据库简单介绍
数据库三层结构
1.所谓安装Mysq数据库,就是在主机安装一个数据库管理系统(DBMS),这个管理程序可以管理多个数据库。DBMS(database manage system)
2.一个数据库中可以创建多个表,以保存数据(信息)。
数据在数据库中的存储形式
SQL语句分类
- DDL:数据定义语句 [create 表,库....]
- DML:数据操作语句 [增加 insert ,修改 update,删除 delete]
- DQL:数据查询语句 [select]
- DCL:数据控制语句 [管理数据库:比如用户权限 grant revoke]
创建数据库
#使用指令创建数据库
CREATE DATABASE DB01;
#删除数据库
DROP DATABASE DB01;
#创建一个使用 utf8 字符集的 DB02 数据库
CREATE DATABASE DB02 CHARACTER SET utf8; #设置字符集
#创建一个使用 utf8 字符集,并带校对规则的的 DB03 数据库
CREATE DATABASE hsp_db03 CHARACTER SET utf8 COLLATE utf8_bin; #设置字符集和校对规则
注意事项和细节
- CHARACTER SET:指定数据库采用的字符集,如果不指定字符集,默认utf8
- COLLATE:指定数据库字符集的校对规则(常用的 utf8 bin、 utf8 general ci 注意默认是 utf8 general ci)
- 校对规则:utf8_bin 区分大小,utf8_general_ci不区分大小写
- 表不指定字符集和校对规则则默认使用数据库的字符集和校对规则
查看、删除数据库
#显示数据库
SHOW DATABASES
#查看前面创建的数据库 DB01
SHOW CREATE DATABASE `DB01` #在创建数据库时,为了规避关键字,可以使用反引号解决
#删除 DB01 数据库
DROP DATABASE DB01
备份、恢复数据库
语法
#备份数据库(在dos模式下备份)
mysql -u 用户名 -p -B 数据库1 数据库2 数据库n > 文件名.sql
#恢复数据库(进入mysql命令行执行)
source 文件名.sql
例子
#备份数据库
mysqldump -u root -p -B DB01 > D:\java\mysql\tmp01.sql
#恢复数据库
source D:\java\mysql\tmp01.sql
#第二个恢复方法:直接将sql文件的内容复制到查询编辑器中执行
备份、恢复数据库中的表
语法
#备份表
mysql -u 用户名 -p 数据库 表1 表2 表n > 文件名.sql
创建表
语法
create table table_name
(
field1 datatype,
field2 datatype,
field3 datatype
)character set 字符集 collate 校对规则 engine 存储引擎
fileld:指定列名 datatype:指定列类型(字段类型)
character set:如不指定则为所在数据库字符集
collate:如不指定则为所在数据库校对规则
engine:引擎
例子
CREATE TABLE `USER`
(
id int,
`name` varchar(255),
`password` varchar(255),
birthday date
)character set utf8 collate utf8_bin engine INNODB;
MySQL常用数据类型
数值类型
数据类型 | 说明 |
---|---|
BIT(M) | 位类型,M指定位数,默认值为1,范围1-64 |
TINYINT [unsigned] | 占1个字节,带符号的范围-128到127,无符号范围0到255。默认是有符号 |
SMALLINT [unsigned] | 占2个字节,带符号的范围 负的215到215-1,无符号范围0到2^16-1。默认是有符号 |
MEDIUMINT [unsigned] | 占3个字节,带符号的范围 负的223到223-1,无符号范围0到2^24-1。默认是有符号 |
INT [unsigned] | 占4个字节,带符号的范围 负的231到231-1,无符号范围0到2^32-1。默认是有符号 |
BIGINT [unsigned] | 占8个字节,带符号的范围 负的263到263-1,无符号范围0到2^64-1。默认是有符号 |
FLOAT [unsigned] | 占用空间4个字节 |
DOUBLE [unsigned] | 比float精度更大的小数,占用空间8个字节 |
DECIMAL(M,D) [unsigned] | 定点数 M指定长度,D表示小数点的位数 |
整数
小数
- FLOAT//Float//单精度精度
- DOUBLE [UNSIGNED]//Double//双精度
- DECIMAL[M, D] [UNSIGNED]//自定义
注意事项和细节
- decimal可以支持更加精确的小数位
- M是小数位数(精度)的总数,D是小数点(标度)后面的位数。
- 如果D是0,则值没有小数点或分数部分。M最大65,D最大是30。如果D被省略,默认是0。如果M被省略,默认是10
- 建议:如果希望小数的精度高,推荐使用decimal
BIT注意事项和细节
- bit 字段显示时,按照位的方式显示
- 查询的时候仍然可以用使用数值查询
- 如果一个值只有 0,1可以考虑使用 bit(1)可以节约空间位类型
- M指定位数,默认值1,范围1-64使用不多
有符号的定义
create table t01(id int) #默认是无符号的
create table t01(id int unsigned) #有符号的
二进制类型
数据类型 | 说明 |
---|---|
BLOB | 0到2^16-1 |
LONGBLOB | 0到2^32-1 |
文本类型
数据类型 | 说明 |
---|---|
CHAR(size) | 固定长度字符串,最大为255个字符 |
VARCHAR(size) | 可变长度字符串 最大65535个字节 |
TEXT LONGTEXT | 文本 TEXT 0到2^16 LONGTEXT 0到 2^32 |
字符串
- CHAR (size)固定长度宇符串 最大255 字符
- VARCHAR(size)可变长度字符串最大65532字节 [utf8编码最大21844字符1-3个字节用于记录大小]
注意事项和细节
- char(4) 这个4表示字符数(最大255),不是字节数,不管是中文还是宇母都是放四个,按字符计算
- varchar(4) 这个4表示字符数,不管是字母还是中文都以定义好的表的编码来存放数据
- char(4) 是定长
- varchar(4) 是变长,就是说,如果你插入了’aa’,实际占用空间大小并不是4个字符,而是按照实际占用空间来分配(说明:varchar本身还需要占用1-3个字节来记录存放内容长度)
- 查询速度: char > varchar
- 存放文本时,也可以使用 Text 数据类型、可以将TEXT列视为VARCHAR列,注意 Text 不能有默认值.大小 0-2^16字节
如果希望存放更多字符,可以选择MEDIUMTEXT 0-2^24 或者 LONGTEXT 0~2^32
日期类型
数据类型 | 说明 |
---|---|
DATE | YYYY-MM-DD 存放年月日 |
DATETIME | YYYY-MM-DD HH:MM:SS 存放年月日时分秒 |
TIME | HH:MM:SS 存放时分秒 |
TIMESTAMP | 时间戳,它用于自动记录insert,update操作的时间 |
基本使用
CREATE TABLE t01
(
t1 date,
t2 datetime,
#时间戳,默认更新当前时间
t3 TIMESTAMP not null
default CURRENT_TIMESTAMP on UPDATE CURRENT_TIMESTAMP
);
修改表
添加列
alter table tablename
add (column dataType [default expr]
[,column dataType]...);
修改列
alter table tablename
modify (column dataType [default expr]
[,column dataType]...);
删除列
alter table tablename
drop (column);
修改表名
rename table 表名 to 新表名
修改字符集
alter table 表名 character set 字符集
例
-- user表上增加一个img列,varchar类型(要求在birthday后面)
alter table user
add img varchar(100) not null default '' -- default后面表示默认值
after birthday;
desc user -- 查看表结构
-- 修改img列,使其长度为50
alter table user
modify img varchar(50) not null default '';
-- 删除img列
alter table user
drop img;
-- 将表名修改为user01
rename table user to user01;
-- 修改表的字符集为utf8
alter table user01 character set utf8;
-- 将列名name修改为user_name
alter table user01
change `name` `user_name` varchar(32)
not null default '';
CRUD
insert
语法
insert into table_name [(column [,column....])]
values (value [,value...])
例
-- 创建一个商品表goods(id int,goods_name varchar(10),price double)
-- 添加2条记录
create table `goods`
(
id int,
goods_name varchar(10),
price double
);
insert into `goods` (id,goods_name,price)
values(10,'华为手机',2000);
insert into `goods` (id,goods_name,price)
values(20,'苹果手机',3000);
注意事项和细节
- 插入的数据应与字段的数据类型相同
- 数据的长度应在列的规定范围内
- 在values中列出的数据位置必须与被加入的列的排列位置相对应
- 字符和日期型数据应包含在单引号中
- 列可以插入空值[前提是该字段允许为空]
- insert into tab name (列名…)values(),(),() 形式添加多条记录
- 如果是给表中的所有字段添加数据,可以不写前面的字段名称
- 默认值的使用,当不给某个字段值时,如果有默认值就会添加默认值,否则报错,使用default可以指定默认值
update
基本语法
update table_name set col_name1=expr1 [,col_name2=expr2 ...]
[where where_definition];
例
-- 在goods表上操作
-- 将所有数据的价格修改为1000
update goods set price = 1000;
-- 将 华为手机 的价格设置为5000
update goods set price = 5000
where goods_name = '华为手机';
-- 将 苹果手机 的价格上涨1000
update goods set price = price + 1000
where goods_name = '苹果手机';
注意事项和细节
- UPDATE语法可以用新值更新原有表行中的各列
- SET子句指示要修改哪些列和要给予哪些值
- WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行
- 如果需要修改多个字段,可以通过 set 字段1=值1,字段2=值2...
-- 可以修改多个列
update goods
set goods_name = '小米手机' ,price = 3000
where id = 20;
delete
基本语法
delete from tbl_name
[where where_definition];
例
-- 删除emp表中名为'老妖怪'的记录
delete from emp
where `name` = '老妖怪';
-- 删除表中所有记录
delete from emp;
-- delete 语句不能删除某一列的值(可使用update设为null或' ')
update emp set job = ' ';
注意事项和细节
- 如果不使用where子句,将删除表中所有数据
- Delete语句不能删除某一列的值(可使用update 设为 null 或者")
- 使用delete语句仅删除记录,不删除表本身,可以使用drop删除表
select
基本语法
select [distinct] *|{column1,column2,column3...}
from table_name;
1. Select 指定查询哪些列的数据
2. column指定列名
3. *表示指定查询哪张表
4. from指定查询哪张表
5. DISTINCT可选,指显示结果时,是否去掉重复数据
例
-- 操作student表
-- 查询表中所有学生的信息
select * from student;
-- 查询表中所有学生的姓名和对应的英语成绩
select `name`,english from student;
-- 过滤表中重复数据,要查询的记录,每个字段相同才会去重
select distinct * from student;
使用表达式对查询的列进行运算
select *|{column1|expression,column2|expression...}
from table_name;
在select语句中可使用as语句
select column_name as 别名 from table_name;
例
-- 统计每个学生的总分
select `name`,(chinese+english+math)
from student;
-- 在所有学生总分加10分
select `name`,(chinese+english+math+10)
from student;
-- 使用别名表示学生分数
select `name`,(chinese+english+math) as total_score
from student;
在where子句中经常使用的运算符
比较运算符
运算符 | 描述 |
---|---|
> < <= >= = <> != | 大于、小于、大于(小于)等于、等于、不等于 |
between...and... | 显示在某一区间的值 |
in(set) | 显示在in列表的值 |
like not like | 模糊查询 |
is null | 判断是否为空 |
逻辑运算符
运算符 | 描述 |
---|---|
and | 多个条件同时成立 |
or | 多个条件任一成立 |
not | 不成立 |
例
-- 查询姓名为赵云的学生成绩
select * from student
where `name` = '赵云';
-- 查询英语成绩大于90的同学
select * from student
where english > 90;
-- 查询总分大于200的所有同学
select * from student
where (chinese+english+math) > 200;
-- 查询math大于60并且id大于4的学生成绩
select * from student
where math>60 and id>4;
-- 查询英语成绩大于语文成绩的同学
select * from student
where english > chinese;
-- 查询总分大于200并且数学成绩小于语文成绩的姓刘的学生
-- 刘% 表示名字以刘开头 %表示0到多
select * from student
where (chinese+english+math)>200
and (math<chinese) and (`name` like '刘%');
-- 查询英语分数在80到90之间的同学
select * from student
where english between 80 and 90;
-- 第二种
select * from student
where english >= 80 and english <= 90;
-- 查询数学成绩为89、90、91的同学
select * from student
where math in(89,90,91);
-- 第二种
select * from student
where math = 89 or math = 90 or math = 91;
-- 查询所有姓张的学生成绩
select * from student
where `name` like '张%';
-- 查询数学分>80,语文分>80的同学
select * from student
where math > 80 and chinese > 80;
order by排序查询
基本语法
select column1,column2,column3...
from table_name
order by column asc|desc;
注意事项和细节
- Order by 指定排序的列,排序的列既可以是表中的列名,也可以是select语句后指定的列名
- AsC 升序[默认]、Desc 降序
- ORDER BY 子句应位于SELECT语句的结尾
例
-- 对数学成绩排序后输出[升序]
select * from student
order by math;
-- 按总分从高到低排序
select `name`,(chinese+english+math) as total_score from student
order by total_score desc;
-- 对姓刘的学生成绩排序输出(升序)
select `name`,(chinese+english+math) as total_score from student
where `name` like '刘%'
order by total_score;
合计/统计函数
count
count返回行的总数
基本语法
select count(*)|count(列名) from table_name
[where where_definition];
例
-- 统计一个班级共有多少学生?
SELECT COUNT(*) FROM student;
-- 统计数学成绩大于90的学生有多少个?
SELECT COUNT(*) FROM student
WHERE math > 90
-- 统计总分大于250的人数有多少?
SELECT COUNT(*) FROM student
WHERE (math + english + chinese) > 250
-- count(*) 和 count(列) 的区别
-- 解释 :count(*) 返回满足条件的记录的行数
-- count(列): 统计某列满足条件的有多少个,但是会排除 为null的情况
sum
sum函数返回满足where条件的行的和 一般使用在数值列
基本语法
select sum(列名) {,sum(列名)...} from table_name
[where where_definition];
例
-- 统计一个班级数学总成绩?
SELECT SUM(math) FROM student;
-- 统计一个班级语文、英语、数学各科的总成绩
SELECT SUM(math),SUM(english),SUM(chinese) FROM student;
-- 统计一个班级语文、英语、数学的成绩总和
SELECT SUM(math + english + chinese) FROM student;
-- 统计一个班级语文成绩平均分
SELECT SUM(chinese)/ COUNT(*) FROM student;
avg
avg函数返回满足where条件的一列平均值
基本语法
select avg(列名) {,avg(列名)...} from table_name
[where where_definition];
例
-- 求一个班级数学平均分
SELECT AVG(math) FROM student;
-- 求一个班级总分平均分
SELECT AVG(math + english + chinese) FROM student;
max/min
max/min函数返回满足where条件的一列的最大/最小值
基本语法
select max(列名) from table_name
[where where_definition];
例
-- 演示max 和 min的使用
-- 求班级最高分和最低分(数值范围在统计中特别有用)
SELECT MAX(math + english + chinese), MIN(math + english + chinese)
FROM student;
-- 求出班级数学最高分和最低分
SELECT MAX(math) AS math_high_socre, MIN(math) AS math_low_socre
FROM student;
gruop by
group by子句对列进行分组
基本语法
select column1,column2,column3... from table_name
group by column;
可以使用having子句对分组结果进行过滤
select column1,column2,column3... from table_name
group by column having...;
例
-- 创建表用于测试使用
CREATE TABLE dept( /*部门表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
);
INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK'),
(20, 'RESEARCH', 'DALLAS'),
(30, 'SALES', 'CHICAGO'),
(40, 'OPERATIONS', 'BOSTON');
-- 员工表
CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
mgr MEDIUMINT UNSIGNED ,/*上级编号*/
hiredate DATE NOT NULL,/*入职时间*/
sal DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2) ,/*红利 奖金*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
);
-- 添加测试数据
INSERT INTO emp VALUES(7369, 'SMITH', 'CLERK', 7902, '1990-12-17', 800.00,NULL , 20),
(7499, 'ALLEN', 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30),
(7521, 'WARD', 'SALESMAN', 7698, '1991-2-22', 1250.00, 500.00, 30),
(7566, 'JONES', 'MANAGER', 7839, '1991-4-2', 2975.00,NULL,20),
(7654, 'MARTIN', 'SALESMAN', 7698, '1991-9-28',1250.00,1400.00,30),
(7698, 'BLAKE','MANAGER', 7839,'1991-5-1', 2850.00,NULL,30),
(7782, 'CLARK','MANAGER', 7839, '1991-6-9',2450.00,NULL,10),
(7788, 'SCOTT','ANALYST',7566, '1997-4-19',3000.00,NULL,20),
(7839, 'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),
(7844, 'TURNER', 'SALESMAN',7698, '1991-9-8', 1500.00, NULL,30),
(7900, 'JAMES','CLERK',7698, '1991-12-3',950.00,NULL,30),
(7902, 'FORD', 'ANALYST',7566,'1991-12-3',3000.00, NULL,20),
(7934,'MILLER','CLERK',7782,'1992-1-23', 1300.00, NULL,10);
-- 工资级别
#工资级别表
CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*工资级别*/
losal DECIMAL(17,2) NOT NULL, /* 该级别的最低工资 */
hisal DECIMAL(17,2) NOT NULL /* 该级别的最高工资*/
);
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);
-- GROUP by用于对查询的结果分组统计,
-- having子句用于限制分组显示结果.
-- 如何显示每个部门的平均工资和最高工资
SELECT AVG(sal), MAX(sal) , deptno
FROM emp GROUP BY deptno;
-- 显示每个部门的每种岗位的平均工资和最低工资
SELECT AVG(sal), MIN(sal) , deptno, job
FROM emp GROUP BY deptno, job;
-- 显示平均工资低于2000的部门号和它的平均工资
SELECT AVG(sal), deptno
FROM emp GROUP BY deptno
HAVING AVG(sal) < 2000;
-- 使用别名
SELECT AVG(sal) AS avg_sal, deptno
FROM emp GROUP BY deptno
HAVING avg_sal < 2000;
字符串函数
例
-- 返回字符串字符集
select charset(ename) from emp;
-- 连接字符串
select concat(ename,' 工作是 ',job) from emp;
-- 返回子串在字符串中出现的位置,没有返回0
-- DUAL亚元表,系统表 可以作为测试表使用
select instr('hello','l') from DUAL;
-- 转换成大写
select ucase(ename) from emp;
-- 转换成小写
select lcase(ename) from emp;
-- 从字符串左边取length个字符
select left(ename,2) from emp;
select right(ename,2) from emp; -- 从右边取
-- 返回字符串长度 按照字节
select length(ename) from emp;
-- 字符串替换
select ename,replace(job,'MANAGER','经理') from emp; -- 将MANAGER替换为经理
-- 比较两字符串大小
select strcmp('a','b') from DUAL;
-- 截取字符串
select substring(ename,1,2) from emp;
-- 去除空格
select trim(' a ') from DUAL; -- 全部空格
select ltrim(' a ') from DUAL; -- 左边空格
select rtrim(' a ') from DUAL; -- 右边空格
数学相关函数
例
-- ABS(num) 绝对值
SELECT ABS(-10) FROM DUAL;
-- BIN (decimal_number )十进制转二进制
SELECT BIN(10) FROM DUAL;
-- CEILING (number2 ) 向上取整, 得到比num2 大的最小整数
SELECT CEILING(-1.1) FROM DUAL;
-- CONV(number2,from_base,to_base) 进制转换
-- 下面的含义是 8 是十进制的8, 转成 2进制输出
SELECT CONV(8, 10, 2) FROM DUAL;
-- 下面的含义是 8 是16进制的8, 转成 2进制输出
SELECT CONV(16, 16, 10) FROM DUAL;
-- FLOOR (number2 ) 向下取整,得到比 num2 小的最大整数
SELECT FLOOR(-1.1) FROM DUAL;
-- FORMAT (number,decimal_places ) 保留小数位数(四舍五入)
SELECT FORMAT(78.125458,2) FROM DUAL;
-- HEX (DecimalNumber ) 转十六进制
-- LEAST (number , number2 [,..]) 求最小值
SELECT LEAST(0,1, -10, 4) FROM DUAL;
-- MOD (numerator ,denominator ) 求余
SELECT MOD(10, 3) FROM DUAL;
-- RAND([seed]) RAND([seed]) 返回随机数 其范围为 0 ≤ v ≤ 1.0
-- 1. 如果使用 rand() 每次返回不同的随机数 ,在 0 ≤ v ≤ 1.0
-- 2. 如果使用 rand(seed) 返回随机数, 范围 0 ≤ v ≤ 1.0, 如果seed不变,
-- 该随机数也不变了
SELECT RAND() FROM DUAL;
日期时间函数
例
-- 日期时间相关函数
-- CURRENT_DATE ( ) 当前日期
SELECT CURRENT_DATE() FROM DUAL;
-- CURRENT_TIME ( ) 当前时间
SELECT CURRENT_TIME() FROM DUAL;
-- CURRENT_TIMESTAMP ( ) 当前时间戳
SELECT CURRENT_TIMESTAMP() FROM DUAL;
SELECT NOW() FROM DUAL;
-- 创建测试表 信息表
CREATE TABLE mes(
id INT ,
content VARCHAR(30),
send_time DATETIME);
-- 添加一条记录
INSERT INTO mes
VALUES(1, '北京新闻', CURRENT_TIMESTAMP());
INSERT INTO mes VALUES(2, '上海新闻', NOW());
INSERT INTO mes VALUES(3, '广州新闻', NOW());
-- 显示所有新闻信息,发布日期只显示 日期,不用显示时间.
SELECT id, content, DATE(send_time)
FROM mes;
-- 请查询在10分钟内发布的新闻
SELECT *
FROM mes
WHERE DATE_ADD(send_time, INTERVAL 10 MINUTE) >= NOW()
SELECT *
FROM mes
WHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE)
-- 求出 2011-11-11 和 1990-1-1 相差多少天
SELECT DATEDIFF('2011-11-11', '1990-01-01') FROM DUAL;
-- 求出你活了多少天? 1986-11-11 出生
SELECT DATEDIFF(NOW(), '1986-11-11') FROM DUAL;
SELECT TIMEDIFF('10:11:11', '06:10:10') FROM DUAL;
-- YEAR|Month|DAY| DATE (datetime )
SELECT YEAR(NOW()) FROM DUAL;
SELECT MONTH(NOW()) FROM DUAL;
SELECT DAY(NOW()) FROM DUAL;
SELECT MONTH('2013-11-10') FROM DUAL;
-- unix_timestamp() : 返回的是1970-1-1 到现在的秒数
SELECT UNIX_TIMESTAMP() FROM DUAL;
-- FROM_UNIXTIME() : 可以把一个unix_timestamp 秒数[时间戳],转成指定格式的日期
-- %Y-%m-%d 格式是规定好的,表示年月日
-- 意义:在开发中,可以存放一个整数,然后表示时间,通过FROM_UNIXTIME转换
--
SELECT FROM_UNIXTIME(1618483484, '%Y-%m-%d') FROM DUAL;
SELECT FROM_UNIXTIME(1618483100, '%Y-%m-%d %H:%i:%s') FROM DUAL;
加密和系统
例
-- 查询用户
select user() from DUAL; -- 格式:用户@IP地址
-- 查询当前使用数据库名称
select database() ;
-- 为字符串算出一个md5 32的字符串进行加密
select MD5('passwd') from DUAL;
-- 加密函数 mysql数据库的用户密码就是password函数加密
select password('passwd') from DUAL;
select * from mysql.user; -- 查询mysql用户表
流程控制函数
例
select if(true,'真','假') from DUAL;
select ifnull('null','aaa') from DUAL;
select case
when true then 'a'
when false then 'b'
else 'c' end;
-- 查询emp表,如果comm是null,则显示0.0
select ename, if(comm is null,0.0,comm) -- 判断是否为空 使用is null 不为空is not null
from emp;
-- 第二种
select ename,ifnull(comm,0.0)
from emp;
-- 如果emp表的job是CLERK则显示职员,如果是MANAGER则显示经理
-- 如果是SALESMAN则显示销售人员,其它正常显示.
select ename,(case
when job = 'CLERK' then '职员'
when job = 'MANAGER' then '经理'
when job = 'SALESMAN' then '销售人员'
else job end) as job
from emp;
表查询--增强
-- 查找在1992-01-01后入职的员工
-- 在mysql中,日期类型可以直接比较
select * from emp
where hiredate > '1992-01-01';
-- % 表示0到多个任意字符
-- _ 表示单个任意字符
-- 显示首字母为S的员工的姓名和工资
select ename,sal
from emp
where ename like 'S%';
-- 显示第三个字符为大写O的所有员工的姓名和工资
select ename,sal
from emp
where ename like '__O%';
-- 按照工资从低到高的顺序,显示雇员的信息
select * from emp
order by sal;
-- 按照部门号升序而雇员的工资降序排列,显示雇员信息
select * from emp
order by deptno asc ,sal desc;
分页查询
-- 按照雇员的序号升序取出,每页显示3条记录
-- 第1页
select * from emp
order by empno
limit 0,3;
-- 第2页
select * from emp
order by empno
limit 3,3;
-- 第3页
select * from emp
order by empno
limit 6,3;
-- 公式
select * from emp
order by empno
limit 每页显示的记录数 * (页码-1) , 每页显示的记录数;
-- 显示每种岗位的雇员数、平均工资
select job,count(*) as '人数',avg(sal) from emp
group by job;
-- 显示雇员总数,以及获得补助的雇员数
select count(*),count(comm)
from emp;
-- 显示雇员总数,以及没有获得补助的雇员数
select count(*),count(if(comm is null,1,null)) -- 这里的1只是返回一个非空值,可是是非空的任何值
from emp;
select count(*),count(*)-count(comm)
from emp;
-- 显示管理者的总人数
select count(distinct mgr)
from emp;
-- 显示雇员的最大差额
select max(sal)-min(sal)
from emp;
多表查询
-- 多表查询
-- 显示雇员名,雇员工资及所在部门的名字 【笛卡尔集】
SELECT ename,sal,dname,emp.deptno
FROM emp, dept
WHERE emp.deptno = dept.deptno
-- 如何显示部门号为10的部门名、员工名和工资
SELECT ename,sal,dname,emp.deptno
FROM emp, dept
WHERE emp.deptno = dept.deptno and emp.deptno = 10
-- 显示各个员工的姓名,工资,及其工资的级别
select ename, sal, grade
from emp , salgrade
where sal between losal and hisal;
自连接
自连接是指在同一张表的连接查询
-- 显示公司员工和他的上级的名字
select worker.ename '员工',boss.ename '上级'
from emp worker,emp boss
where worker.mgr = boss.empno;
子查询
子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询。
单行子查询是指只返回一行数据的子查询语句。
多行子查询指返回多行数据的子查询语句。
-- 显示与SMITH同一部门的所有员工
select * from emp
where deptno = (select deptno from emp where ename='SMITH');
-- 查询和部门10的工作相同的雇员的名字、岗位、工资、部门号,但是不含10自己的
select ename,job,sal,deptno
from emp
where job in (
select distinct job from emp where deptno = 10)
and deptno != 10;
all any
-- 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
select ename,sal,deptno from emp
where sal >
all(select sal from emp where deptno = 30 );
select ename,sal,deptno from emp
where sal >
(select max(sal) from emp where deptno = 30 );
子查询做临时表
-- 查询ecshop中各个类别中,价格最高的商品
select goods_id, ecs_goods.cat_id, goods_name, shop_price
from (
SELECT cat_id , MAX(shop_price) as max_price
FROM ecs_goods
GROUP BY cat_id
) temp , ecs_goods
where temp.cat_id = ecs_goods.cat_id
and temp.max_price = ecs_goods.shop_price
多列子查询
-- 查询与ALLEN的部门和岗位完全相同的所有雇员(不包括ALLEN)
select * from emp
where (deptno,job) = (
select deptno,job from emp
where ename = 'ALLEN'
)and ename != 'ALLEN';
-- 临时表的写法
select ename,sal,emp.job,emp.deptno
from (select deptno,job from emp
where ename = 'ALLEN') as tmp,emp
where tmp.deptno = emp.deptno
and tmp.job = emp.job and ename != 'ALLEN';
表复制
create table tmptab
(
id int,
`name` varchar(20)
);
-- 复制数据
insert into tmptab(id,`name`)
select empno,`ename` from emp;
-- 自我复制
insert into tmptab
select * from tmptab;
-- 删除表的重复数据
create table my_tab like emp; -- 将emp表结构复制到my_tab
insert into my_tab
select * from emp;
create table my_tmp like emp;
-- 将my_tab的记录通过distinct去重后,把记录复制到my_tmp
insert into my_tmp
select distinct * from my_tab;
-- 删除my_tab的记录
delete from my_tab;
-- 把my_tmp表的数据复制到my_tab
insert into my_tab
select * from my_tmp;
-- 删除my_tmp
drop table my_tmp;
合并查询
基本介绍
为了合并多个selecti语句的结果,可以使用集合操作符号 union , union all
union all 该操作符用于取得两个结果集的并集。当使用该操作符时,不会取消重复行。
union 该操作赋与union all相似,但是会自动去掉结果集中重复行。
-- union all 就是将两个查询结果合并,不会去重
SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5
UNION ALL
SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3
-- union 就是将两个查询结果合并,会去重
SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5
UNION
SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3
表外连接
左外连接:左侧的表完全显示我们就说是左外连接
右外连接:右侧的表完全显示我们就说是右外连接
-- 创建 stu
CREATE TABLE stu (
id INT,
`name` VARCHAR(32));
INSERT INTO stu VALUES(1, 'jack'),(2,'tom'),(3, 'kity'),(4, 'nono');
SELECT * FROM stu;
-- 创建 exam
CREATE TABLE exam(
id INT,
grade INT);
INSERT INTO exam VALUES(1, 56),(2,76),(11, 8);
SELECT * FROM exam;
-- 使用左连接
-- (显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
SELECT `name`, stu.id, grade
FROM stu LEFT JOIN exam
ON stu.id = exam.id;
-- 使用右外连接(显示所有成绩,如果没有名字匹配,显示空)
-- 即:右边的表(exam) 和左表没有匹配的记录,也会把右表的记录显示出来
SELECT `name`, stu.id, grade
FROM stu RIGHT JOIN exam
ON stu.id = exam.id;
-- 列出部门名称和这些部门的员工信息(名字和工作),
-- 同时列出那些没有员工的部门名。
-- 使用左外连接实现
SELECT dname, ename, job
FROM dept LEFT JOIN emp
ON dept.deptno = emp.deptno
-- 使用右外连接实现
SELECT dname, ename, job
FROM emp RIGHT JOIN dept
ON dept.deptno = emp.deptno
约束
约束用于确保数据库的数据满足特定的规则,在mysql中,约束包括:not null,unique,primary key,foreign key和check五种.
主键
基本介绍
用于唯一的标示表行的数据,当定义主键约束后,该列不能重复
基本语法
CREATE TABLE tablename
(id INT PRIMARY KEY,
`name` VARCHAR(32));
CREATE TABLE tablename
(id INT,
`name` VARCHAR(32)
PRIMARY KEY(id,`name`)); //复合主键
注意事项和细节
- primary key不能重复而且不能为null
- 一张表最多只能有一个主键,但可以是复合主键
- 主键的指定方式有两种:
直接在字段名后指定:字段名 primakry key
在表定义最后写: primary key(列名) - 使用desc 表名,可以看到primary key的情况
not null
基本介绍
如果在列上定义了not null,那么当插入数据时,必须为列提供数据
unique
基本介绍:
如果在列上定义了not null,那么当插入数据时,必须为列提供数据
基本语法
CREATE TABLE table_name
(id INT UNIQUE , -- 表示 id 列是不可以重复的.
`name` VARCHAR(32) ,
email VARCHAR(32)
);
-- 一张表可以有多个unique字段
CREATE TABLE table_name
(id INT UNIQUE , -- 表示 id 列是不可以重复的.
`name` VARCHAR(32) UNIQUE , -- 表示name不可以重复
email VARCHAR(32)
);
注意事项和细节
- 如果没有指定not null ,则 unique 字段可以有多个null
- 一张表可以有多个unique字段
外键
基本介绍
用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或是unique约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null
基本语法
CREATE TABLE tablename
(id INT ,
`name` VARCHAR(32))
FOREIGN KEY (本表字段) REFERENCES 主表名(主键或unique字段));
注意事项和细节
- 外键指向的表的字段,要求是primary key 或者是unique
- 表的类型是innodb,这样的表才支持外键
- 外键字段的类型要和主键字段的类型一致(长度可以不同)
- 外键宇段的值,必须在主键字段中出现过,或者为null 前提是外键字段允许为null
- 一旦建立主外键的关系,数据不能随意删除了
-- 创建 主表 my_class
CREATE TABLE my_class (
id INT PRIMARY KEY , -- 班级编号
`name` VARCHAR(32) NOT NULL DEFAULT '');
-- 创建 从表 my_stu
CREATE TABLE my_stu (
id INT PRIMARY KEY , -- 学生编号
`name` VARCHAR(32) NOT NULL DEFAULT '',
class_id INT , -- 学生所在班级的编号
-- 下面指定外键关系
FOREIGN KEY (class_id) REFERENCES my_class(id))
check
基本介绍
用于强制行数据必须满足的条件
oracle和sql server均支持check,但是mysql5.7目前还不支持check,只做语法校验,但不会生效。
CREATE TABLE t23 (
id INT PRIMARY KEY,
`name` VARCHAR(32) ,
sex VARCHAR(6) CHECK (sex IN('man','woman')),
sal DOUBLE CHECK ( sal > 1000 AND sal < 2000)
);
自增长
整数列添加记录时进行自我增长
基本语法
CREATE TABLE `user` (
`id` INT NOT NULL AUTO_INCREMENT);
ALTER TABLE `uesr` AUTO_INCREMENT = 100;
添加方式
- insert into xxx (字段1,字段2..…)values(null,'值'...);
- insert into xxx (字段2...)values('值1','值2'...);
- insert into xxx values(null,'值1',...)
注意事项和细节
- 一般来说自增长是和primary key 配合使用的
- 自增长也可以单独使用[但是需要配合一个unique
- 自增长修饰的字段为整数型(也可以为小数)
- 自增长默认从 1开始,你也可以通过如下命令修改alter
table 表名 auto_increment=新的开始值 - 如果你添加数据时,给自增长字段(列) 指定的有值,则以指定的值为准
索引
形成一个索引的数据结构,比如二叉树
索引的代价:磁盘占用,对dml(update delete insert)语句的效率影响
1.主键索引,主键自动的为主索引(类型Primary key)
2.唯一索引(UNIQUE)
3.普通索引(INDEX)
4.全文索引(FULLTEXT))[适用于MyISAM] 一般开发,不使用mysql自带的全文索引,而是使用:全文搜索Solr和 ElasticSearch (ES)
CREATE TABLE t25 (
id INT ,
`name` VARCHAR(32));
-- 添加索引
-- 添加唯一索引
CREATE UNIQUE INDEX id_index ON t25 (id);
-- 添加普通索引方式1
CREATE INDEX id_index ON t25 (id);
-- 添加普通索引方式2
ALTER TABLE t25 ADD INDEX id_index (id)
-- 添加主键索引
CREATE TABLE t26 (
id INT ,
`name` VARCHAR(32));
ALTER TABLE t26 ADD PRIMARY KEY (id)
-- 删除索引
DROP INDEX id_index ON t25
-- 删除主键索引
ALTER TABLE t26 DROP PRIMARY KEY
-- 修改索引 , 先删除,在添加新的索引
-- 查询索引
-- 1. 方式
SHOW INDEX FROM t25
-- 2. 方式
SHOW INDEXES FROM t25
-- 3. 方式
SHOW KEYS FROM t25
-- 4 方式
DESC t25
注意事项和细节
- 较频繁的作为查询条件字段应该创建索引
- 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
- 更新非常频繁的字段不适合创建索引
- 不会出现在WHERE子句中字段不该创建索引
事务
基本介绍
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败
事物和锁
当执行事务操作时(dml语句),mysql会在表上加锁,防止其它用户改表的数据
基本操作
- start transaction — 开始一个事务
- savepoint 保存点名 一 设置保存点
- rollback to 保存点名一 回退事务到保存点
- rollback — 回退全部事务
- commit — 提交事务,所有的操作生效,不能回退
-- 创建一张测试表
CREATE TABLE t27
( id INT,
`name` VARCHAR(32));
-- 开始事务
START TRANSACTION
-- 设置保存点
SAVEPOINT a
-- 执行dml 操作
INSERT INTO t27 VALUES(100, 'tom');
SELECT * FROM t27;
SAVEPOINT b
-- 执行dml操作
INSERT INTO t27 VALUES(200, 'jack');
-- 回退到 b
ROLLBACK TO b
-- 继续回退 a
ROLLBACK TO a
-- 直接回退到事务开始的状态.
ROLLBACK
-- 提交事务
COMMIT
回退事物
保存点是事务中的点 用于取消部分事务,当结束事务时 (commit),会自动的删除该事务所定义的所有保存点,当执行回退事务时,通过指定保存点可以回退到指定的点
提交事物
使用commit语句可以提交事务.当执行了commit语句子后,会确认事务的变化、结束事务、删除保存点、 释放锁,数据生效。当使用commit语句结束事务之后,其它会话将可以查看到事务变化后的新数据
注意事项和细节
- 如果不开始事务,默认情况下,dml操作是自动提交的,不能回滚
- 如果开始一个事务,你没有创建保存点. 你可以执行rollback,默认就是回退到你事务开始的状态
- 你也可以在这个事务中(还没有提交时),创建多个保存点 比如:savepoint aaa;执行 dml , savepoint bbb;
- 回退到更早的保存点则无法会退更晚的保存点
- mysql的事务机制需要innodb的存储引擎还可以使用,myisam不好使
- 开始一个事务 start transaction,set autocommit=off
事务隔离
基本介绍
多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的淮确性
脏读:
当一个事务读取另一个事务尚未提交的修改时,产生脏读
不可重复读:
同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生不可重复读
幻读:
同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读
事务隔离级别
-- 查看当前会话隔离级别
select @@tx_isolation;
-- 查看系统当前隔离级别
select @@global.tx_isolation;
-- 设置当前会话隔离级别
set session transaction isolation level repeatable read; -- 可重复读
-- 设置系统当前隔离级别
set session transaction isolation level repeatable read; -- 可重复读
-- mysql默认的事务隔离级别是 repeatable read
-- 一般情况下,没有特殊要求,不需要修改
全局修改
修改my.ini配置文件在最后加上
#可选参数有:READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ,SERIALIZABLE
[mysqld]
transaction-isolation = REPEATABLE-READ
事务特性
- 原子性 (Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 一致性 (Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态
- 隔离性 (Isolation)事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
- 持久性 (Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来郎使数据库发生故障也不应该对其有任何影响
表类型和存储引擎
基本介绍
-
MySQL表类型由存储引擎(Storage Engines)决定,主要包括MyISAM,innoDB、Memory等
-
MysQL 数据表主要支持六种类型,
分别是:CSV、 Memory、ARCHIVE、MRG MYISAM、 MYISAM、InnoBDB -
分为两类,一类是“事务安全型”(transaction-safe), 比如:InnoDB;其余都是“非事物安全型”(non-transactionsafe)[mysiam] 和 memory]
常用存储引擎
- MyLSAM不支持事物,也不支持外键,访问速度快,对事物完整性没有要求
- InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引
- MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦服务关闭,表中的数据就会丢失掉,表的结构还在
引擎选择
- 如果你的应用不需要事务,处理的只是基本的CRUD操作,那么MyISAM是不二选择,速度快
- 如果需要支持事务,选择InnoDB
- Memory 存储引擎就是将数据存储在内存中,由于没有磁盘IO的等待,速度极快,但由于是内存存储引擎,所做的任何修改在服务器重启后都将消失
修改存储引擎
ALTER TABLE `表名` ENGINE = 存储引擎;
视图
基本介绍
视图是一个虛拟表,其内容由查询定义。同真实的表一样,视图包含列,其数据来自对应的真实表(基表)
视图的总结
1.视图是根据基表(何以是多个基表)来创建的视图是虚拟的表
2.视图也有列,数据来自基表
3.通过视图可以修改基表的数据
4.基表的改变,也会影响到视图的数据
视图的基本使用
create view 视图名 as select语句
alter view 视图名 as select语句
show create view 视图名
drop view 视图名1,视图名2
-- 创建视图
create view emp_view01
as
select empno,ename,job,deptno
from emp;
-- 查看视图
desc emp_view01;
select * from emp_view01;
select ename,job from emp_view01;
-- 查看创建的视图
show create view emp_view01;
-- 删除视图
drop view emp_view01;
-- 多表
create view emp_view
as
select empno 编号,ename 雇员名,dname 部门名,grade 薪水级别
from emp,dept,salgrade
where (emp.deptno = dept.deptno)
and (emp.sal between salgrade.losal and salgrade.hisal);
注意事项和细节
- 创建视图后,到数据库去看,对应视图只有一个视图结构文件(形式:视图名.frm)
- 视图的数据变化会影响到基表,基表的数据变化也会影响到视圈[insert update delete]
- 视图中可以再使用视图,数据仍然来自基表
性质
- 安全:一些数据表有着重要的信息。有些字段是保密的,不能让用户直接看到。这时就可以创建一个视图,在这张视图中只保留一部分字段。这样,用户就可以查询自己需要的字段,不能查看保密的字段
- 性能:关系数据库的数据常常会分表存储,使用外键建立这些表的之间关系。这时,数据库查询通常会用到连接 (JOIN)。这样做不但麻烦,效率相对也比较低。如果建立一个视图,将相关的表和字段组合在一起,就可以避免使用JOIN查询数据
- 灵活:如果系统中有一张1日的表,这张表由于设计的问题,即将被废弃。然而,很多应用都是基于这张表,不易修改。这时就可以建立一张视图,视图中的数据直接映射到新建的表。这样就可以少做很多改动,也达到了升级数据表的目的
用户管理
管理指令
- 创建用户:create user ‘用户名’ @ '允许登录位置’ identified by 密码
- 删除用户:drop user ‘用户名’ @ '允许登录位置'
- 修改密码:SET PASSWORD FOR ‘用户名’ @ '允许登陆位置' = PASSWORD('123456')
-- 'my'@'localhost'表示完整的用户信息
-- 'my'用户名 'localhost'登录的IP
-- '123456'密码,存放到mysql.user表时,进行加密
create user 'my'@'localhost' identified by '123456';
-- 删除用户
drop user 'my'@'localhost';
select `host`,`user` from mysql.user;
-- 修改自己密码
set password = password('123456');
-- 修改别人的密码,需要权限
set password for 'root'@'localhost' = password('123456');
权限管理
给用户授权
基本语法
grant 权限列表 on 库.对象名 to '用户名'@'登录IP' [ identified by '密码']
说明
- 权限列表,多个权限用逗号隔开
- 库.* 代表某个数据库中的所有数据对象(表,视图,存储过程等)
- identified by 可以省略,也可以写出
(1)如果用户存在,就是修改该用户的密码(2)如果用户不存在,就是创建该用户
回收用户授权
基本语法
revoke 权限列表 on 库.对象名 from '用户名'@'登录IP'
权限生效指令
如果权限没有生效,可以执行下面的指令
flush privileges;
例
-- 创建用户 'my' 密码 '123' ,从本地登录
create user 'my'@'localhost' identified by '123';
-- 创建testdb 表news
create database testdb;
create table news
(
id int,
content varchar(50)
);
-- 添加一条测试数据
insert into news
values(100,'aaa');
-- 给my分配查看news表的和添加的权限
grant select,insert
on testdb.news
to 'my'@'localhost';
-- 增加update权限
grant update
on testdb.news
to 'my'@'localhost';
-- 修改my的密码为abc
set password for 'my'@'localhost' = password('abc');
-- 回收my用户在testdb.news所有权限
revoke select,insert,update
on testdb.news
from 'my'@'localhost';
-- 第二种
revoke all
on testdb.news
from 'my'@'localhost';
-- 删除my用户
drop user 'my'@'localhost';
注意事项和细节
- 在创建用户的时候,如果不指定Host,则为%,%表示表示所有IP都有连接权限create user xxx;
- create user 'xxx'@'192.168.1.%’ 表示 xxx用户在 192.168.1.*的ip可以登录mysql
- 在删除用户的时候,如果 host 不是 %,需要明确指定“用户’@'host值‘