MySQL-5.7
1、DBMS描述
DBMS数据库管理软件:Oracle、MySQL、DB2、PostgreSQL...
RDBMS:Relational-关系性数据库。
是以行row和列column形式存在,结合在一起为表table,一组表为库DB。
表和表之间的数据记录有关系,实体和实体之间有关系模型。
E-R模型:entity-relationship。
Oracle、MySQL、SQL Server是行式存储。
列式数据库是将数据按列存储到数据库中:HBase。
1.1、SQL语句定义
SQL语言标准:SQL92和SQL99。
DDL-definition:数据定义语言,包括CREATE、DROP、ALTER...
DML-Manipulation:数据操作语言。INSERT、UPDATE、DELETE、SELECT...
DCL-Control:数据控制语言。GRANT、REVOKE、COMMIT、ROLLBACK、SAVEPOINT...
2、引号和着重号
'' 单引号: 字符串、日期时间类型
"" 双引号: 列名起别名
`` 着重号: `order` MySQL中的关键字
3、大小写
Windows环境:大小写不敏感。ANSI码标准。
Linux环境:大小写敏感。
严格区分大小写: 数据库名、表名、表别名、变量名。
忽略大小写: 关键字、函数名、列名、列别名,字符串类型(Oracle是区分大小写)。
4、 建表
4.1、CREATE TABLE
DROP TABLE IF EXISTS jjc_employee;-- 表存在-删除表
-- CREATE TABLE IF NOT EXISTS jjc_employee | 表存在-跳过创建表
CREATE TABLE jjc_employee (
employee_id BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT 'id',
employee_code VARCHAR ( 30 ) NOT NULL COMMENT '工号',
employee_name VARCHAR ( 30 ) NOT NULL COMMENT '姓名',
birthdate datetime ( 0 ) NULL DEFAULT NULL COMMENT '生日',
credential_type VARCHAR ( 10 ) NULL DEFAULT NULL COMMENT '证件类型',
credential_number VARCHAR ( 30 ) NULL DEFAULT NULL COMMENT '证件号',
gender CHAR ( 1 ) NULL DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
email_address VARCHAR ( 100 ) NULL DEFAULT NULL COMMENT '邮箱',
mobile_phone CHAR ( 30 ) UNIQUE NULL DEFAULT NULL COMMENT '手机号',
detail_address VARCHAR ( 100 ) NULL DEFAULT NULL COMMENT '住址',
dept_id INT ( 11 ) NOT NULL COMMENT '部门id',
hire_date datetime ( 0 ) NULL DEFAULT NULL COMMENT '入职日期',
termination_date datetime ( 0 ) NULL DEFAULT NULL COMMENT '离职日期',
attend_location VARCHAR ( 30 ) NULL DEFAULT NULL COMMENT '',
manager_number VARCHAR ( 30 ) NULL DEFAULT NULL COMMENT '上级工号',
card_type_code CHAR ( 1 ) NULL DEFAULT '1' COMMENT '打卡类型',
card_type_meaning VARCHAR ( 10 ) NULL DEFAULT NULL COMMENT '打卡方式',
is_dimission VARCHAR ( 10 ) NULL DEFAULT NULL COMMENT '',
work_schedule VARCHAR ( 10 ) NULL DEFAULT NULL COMMENT '工作方式',
probation_date datetime ( 0 ) NULL DEFAULT NULL COMMENT '离职日期',
bank VARCHAR ( 100 ) NULL DEFAULT NULL COMMENT '开户行',
bank_number VARCHAR ( 30 ) NULL DEFAULT NULL COMMENT '银行卡号',
PRIMARY KEY ( employee_id ) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 1000000000 COMMENT = '用户信息表' ROW_FORMAT = Dynamic;
-- 根据原有的表结构,创建表,并导入数据
CREATE TABLE employee2
AS
SELECT employee_id emp_id, last_name lname, salary -- 别名将为新表的字段名
FROM employees
WHERE 1=2; -- 不导入数据
1. 主键自增重新赋值
-- 第一个值库名,第二值表名
SELECT auto_increment FROM information_schema.TABLES WHERE table_schema = "jjc" AND table_name = "jjc_employee";
-- 修改自增的值从哪里开始,要注意字段长度,BIGINT 默认有符号19个值
ALTER TABLE jjc_employee auto_increment = 1000000000000000000;
-- 查看表结构
DESC jjc_employee;
2. 表信息
-- 查看表信息
SHOW CREATE TABLE 表名;
-- 查看表结构
DESCRIBE 表名;
4.2、删除表
-- 删除表
DROP TABLE IF EXISTS employees_copy_re;
-- 清空表数据
TRUNCATE TABLE employees_copy_re; -- 不能ROLLBACK
DELETE FROM employees_copy_re; -- 能ROLLBACK
4.3、修改表字段
-- 表重命名
RENAME TABLE employees_copy TO employee_copy_re;
-- 添加字段默认在最后一位
ALTER TABLE employees_copy ADD comm DECIMAL(10,2)
-- 第一位
FIRST;
ALTER TABLE employees_copy ADD email varchar(64)
-- 在指定字段后面
AFTER job;
-- 修改长度 | 一般不改数据类型
ALTER TABLE employees_copy MODIFY first_name varchar(50) DEFAULT '';
-- 重命名字段
ALTER TABLE employees_copy CHANGE salary mon_salary DECIMAL(10,2);
-- 删除字段
ALTER TABLE employees_copy DROP COLUMN mon_salary;
4.4、约束
| 约束关键字 | |
|---|---|
| primary key | 主键、非空且唯一。 |
| not null | 非空 字段名 数据类型 not null |
| unique | 唯一 可以设置多字段组合唯一,在建表的最后 unique key(phone_number,id_card |
| check | 检查约束,5.7不支持,8.0支持。 gender char(2) check (sex in('男','女')), age int check(age>=0 and age<200) |
| default 默认值 | not null default '' 或 defalut 0,不想用null为值,会影响索引查询效率。 |
| foreign key | 外键不建议使用,会影响数据库性能 |
-- 添加唯一键
ALTER TABLE city_details ADD CONSTRAINT uk_city_details_phone_number UNIQUE (phone_number);
-- 删除约束:
DROP INDEX uk_city_details_phone_number ON city_details;
-- 查询所有键、索引:
SHOW INDEX FROM city_details;
1. 唯一约束查询重复数据
-- 添加唯一键
ALTER TABLE city_details
ADD CONSTRAINT uk_city_details_phone_number UNIQUE (phone_number);
-- > 1062 - Duplicate entry '025-025' for key 'uk_city_details_phone_number'
-- 说明该列有重复数据 025-025
-- <> 就是 != | <=>为NULL而生
-- 查询电话号码是否有重复:
SELECT
c1.id,
c1.phone_number,
c2.id,
c2.phone_number
FROM
city_details c1,
city_details c2
WHERE
c1.id <> c2.id
AND c1.phone_number = c2.phone_number
5、字段属性
| 字段 | 描述 |
|---|---|
| int(11) | -2147483648-2147483647,0-4294967295。 这里11的意思:显示宽度,(- 负号 2147483648 )一共11位。 id int(5) 此时的5无意义,插入123就是123,123456也是123456。 但是 id int(5) zerofill 就表示用0填充,如插入123不足5位,为00123。 |
| tinyint(4) | 1个字节,有符号-128-127,无符号UNSIGEED: 0-255。 |
| bigint(20) | 8个字节,-9223372036854775808-9223372036854775807,0-18446744073709551615 |
| decimal(m,d) | 大小取决m,d,m指精度(总长度包含小数点)d表示小数点的位数(大于bigint) decimal(5,2) :m最大65,d最大30(m省略,d默认时10;d省略,默认是0) |
| char() | 0~255字符,定长(不设定值时,插入2个字符,也会占4个字符), char(4) ,表示占4个字符,中英文只能放4个。 |
| varchar() | 变长(不设定值时,插入2个字符,就2个字符), varhcar(255) :0~65535(utf-8(最大21844字符,65535/3)、utf8mb4(最大16383字符)) |
| text | 0~2^16-1,不能有默认值,如果varchar不够用 |
| lontext | 当varchar的长度超过5000,建议创建一个新表用主键来对应,数据用text类型。 最大长度4G。存储原文本内容 |
| blob | 二进制字符串 blob的IO读取速度比longtext速度快(blob字段不存储原文本内容,无法对文本进行搜索功能) |
| date | 3个字节,1000-01-01 ~ 9999-12-03 |
| datetime | 8个字节,1000-01-91 00:00:00 ~ 9999 register_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) |
| timestamp | 有时区需求使用 set time_zone = '+9:00' 东九区。 4个字节,1970-01-01 00:00:00 ~ 2038-01-19 03:14:07 UTC login_time timestamp not null default current_timestamp on update current_timestamp |
6、索引
常见索引包含:主键索引、唯一索引、普通索引(单列、组合)。
6.1、命令操作
-- 查询该查询sql语句的执行效率:
EXPLAIN select * from pms_category where parent_cid = 1;
-- 查询该表的所有的索引列。
SHOW INDEX FROM pms_category;
-- 添加普通索引:
CREATE INDEX pms_category_parend_cid_index ON pms_category ( parent_cid );
-- 联合索引用, 逗号隔开:
CREATE INDEX t_name_index ON teacher ( t_name, t_age );
-- 【索引无法修改,只能删除重新创建】。
-- 删除索引:
DROP INDEX pms_category_parend_cid_index ON pms_category;
6.2、索引优化
| 添加索引优化 | |
|---|---|
| group by + order by两个条件添加联合索引,把分组的条件放在最左边,满足最左匹配原则 | |
| update、delete的where条件字段可以添加索引或联合索引 | |
| distinct字段添加索引 | |
| 区分度高的字段适合添加索引,如id,name 重复度大于10% | 区分度低的字段:gender只包含0、1、2。 |
| 多表join连接时,where条件 + 连接条件创建索引 小表驱动大表。 如:t_type t left join t_book b on t.card = b.card,由于左外连接t_type的全表数据都需要的,我们使用t_book是被驱动表。 建议两个都可以加索引。 | 多字段都要创建索引的情况下,联合索引优于单列索引 |
| 单张表索引不要超过6个。 | |
| 数据量小1000行的表不要使用索引,优化器直接不走索引。 | |
| 不建议使用无序列的值索引,如身份证、uuid。 | |
| 开启慢查询日志:set global slow_query_log = on; 设置long_query_time的阈值:show variables like '%long_query_time%'; 默认10s。 set long_query_time =1; |
6.3、索引失效
| 场景 | 描述 | 演示 | |
|---|---|---|---|
| where:or | 使用UNION ALL | ||
where:NOT != <> !< !> /NOT IN/NOT LIKE | 但不是绝对,看优化器选择 | ||
| where:使用了内置函数 | 索引列login_time上使用了函数,会索引失效 | select * from user where DATE_ADD(login_time, INTERVAL 1 DAY) = 7; | |
| where age+1 | |||
| where字段属性隐式转换 (原来是字符查询时变成了字) | user_id varchar(20) | where user_id = 12; | |
| where like '%' 开头 | 可以使用'x%' | ||
| where 多条件,联合索引没有遵循最左匹配原则 | 假设联合索引(k1,k2,k3), 相当于创建了(k1)、(k1,k2)、(k1,k2,k3), 这就是最左匹配。 | 不会命中索引 select * from t where k2=2; select * from t where k3=3; select * from t where k2=k2 and k3=3; 只会命中k1 select * from t where k1=1 and k3=k3; | |
| 排序时`ASC | DESC`混用 |
6.4、执行效率EXPLAIN
| TYPE | 描述 |
|---|---|
| ALL | 全表扫描 |
| index | 索引全扫描 |
| range | 索引范围扫描,常用语< <= >= between in等操作 |
| ref | 非唯一索引扫描或唯一索引前缀扫描,返回单条记录,常出现在关联查询中 |
| eq_ref | 类似ref,区别在于使用的是唯一索引,使用主键的关联查询 |
| const | 主键或唯一索引 |
| EXTRA | 描述 |
|---|---|
| Using temporary | 使用了临时表保存中间结果,性能特别差,需要重点优化 |
| Using index | 相应的 select 操作中使用了覆盖索引(Coveing Index),避免访问了表的数据行,效率不错 同时出现 using where,意味着无法直接通过索引查找来查询到符合条件的数据 |
| Using filesort | 额外的一次传递,以找出如何按排序顺序检索行,通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。 |
| Using index condition | 在存储引擎层进行数据过滤,而不是在服务层过滤,利用索引现有的数据减少回表的数据。 |
7、INSERT、UPDATE、DELETE
-- 关闭自动提交
SET autocommit = FALSE
-- 根据查询表的数据进行插入 | 注意两个表字段的长度属性要匹配
INSERT INTO employees_copy SELECT * FROM employees
ROLLBACK;
COMMIT;
-- 插入多条数据
INSERT INTO employees_copy ( last_name, email, job_id, hire_date )
VALUES
( 'zhangsan', 'zhangsan@123.com', 'IT_PROG', now( ) ),
( 'lisi', 'lisi@qq.com', 'IT_PROG', now( ) )
-- 修改
UPDATE 表名 SET 列名 WHERE 条件;
-- 删除
DELETE FROM 表名 WHERE 条件;
7.1、UPDATE+JOIN配合关联表修改
UPDATE `stud_personal_profile` spp
JOIN `stud_personal_basic` spb ON spp.`ID` = spb.`profile_id`
SET spb.`birthday` = CONCAT(
SUBSTR( spp.`id_card`, 7, 4 ),'-',
SUBSTR( spp.`id_card`, 11, 2 ),'-',
SUBSTR( spp.`id_card`, 13, 2 )
),
spb.update_date = NOW( ),
spb.update_id = 1
WHERE
( spb.`birthday` IS NULL OR spb.`birthday` = '' )
AND LENGTH( spp.`id_card` ) = 18;
8、查询SELECT
完成的查询语句:SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT ...
聚合函数 max、min、count、sum、avg 不能在where条件中使用。
8.1、分组查询GROUP BY
当使用分组查询,SELECT查询只能包含分组条件和聚合函数。
-- 查询部门下工资最低的 员工名字和工资
SELECT
e1.ename,
e2.min_sal,
e2.deptno
FROM
emp e1
INNER JOIN ( SELECT min( sal ) min_sal, deptno FROM emp GROUP BY deptno ) e2 ON e1.deptno = e2.deptno
AND e1.sal = e2.min_sal
ORDER BY
e2.min_sal
-- 查询每个部门工资大于平均工资的 员工
SELECT
e.*
FROM
emp e
INNER JOIN ( SELECT avg( sal ) avg_sal, deptno FROM emp GROUP BY deptno ) t1 ON e.sal > t1.avg_sal
AND e.DEPTNO = t1.DEPTNO
1. HAVING
group by + having。用于分组之后替代WHERE条件进行过滤,必须配合使用。
-- 查询职位人数大于3的,职位
SELECT job,count( job ) FROM emp GROUP BY JOB HAVING count( job ) > 3
-- 查询10、20、30部门中最高工资大于10000的部门信息
SELECT department_id,MAX( e.salary ) FROM employees e
WHERE e.department_id in (10,20,30)
GROUP BY e.department_id HAVING MAX( e.salary ) > 10000;
-- 查询部门中平均工资大于5000的 所有员工信息
SELECT
e.*,
t.*
FROM
employees e
RIGHT JOIN (
SELECT
e.department_id,
AVG( e.salary ) avg_salary
FROM
employees e
GROUP BY
e.department_id
HAVING
AVG( e.salary ) > 5000
) t ON e.department_id = t.department_id
AND e.salary >= t.avg_salary
8.2、分组统计GROUP_CONCAT
-- separator '_' 表示以下滑线为分割符
SELECT
ssav.attr_id attr_id,
ssav.attr_name attr_name,
ssav.attr_value,
group_concat( DISTINCT info.sku_id separator '_' ) sku_ids
FROM
pms_sku_info info
LEFT JOIN pms_sku_sale_attr_value ssav ON
ssav.sku_id = info.sku_id
WHERE
info.spu_id = 11
GROUP BY
ssav.attr_id,
ssav.attr_name,
ssav.attr_value;
8.3、分页LIMIT
-- 第一页: 0 从0开始该值为offset偏移量,20 每页数量
-- 第二页:20,20
SELECT * FROM jjc_employee
LIMIT 0,20
-- LIMIT pageSize*(pageNum-1) , pageSize
8.4、表连接JOIN ON
MySQL的SQL99语法不支持FULL JOIN 满外连接语法的,但是可以通过UNION ALL + LFET JOIN、RIGHT JOIN 拼接。
8.5、交集UNION、UNION ALL
union all并集。
-- 交集,可自动去重:
SELECT ename, sal, job FROM emp WHERE sal > 2500
UNION
SELECT ename,sal,job FROM emp WHERE job = 'MANAGER';
-- 并集:(推荐使用)
SELECT ename,sal,job FROM emp WHERE sal > 2500
UNION ALL
SELECT ename,sal,job FROM emp WHERE job = 'MANAGER';
8.6、多列子查询、ALL、ANY
-- 查询和SMITH 相同部门、工作的员工,不包含SMITH自己
SELECT
*
FROM
emp e1
WHERE
( e1.deptno, e1.job ) = ( SELECT e.deptno, e.job FROM emp e WHERE e.ename = 'SMITH' )
AND e1.ename != 'SMITH';
-- ALL 查询工资比30部门,所有员工都高的员工
SELECT e.ename,e.sal,e.deptno FROM `emp` e
WHERE e.sal > ALL ( SELECT sal FROM `emp` WHERE deptno = 30 );
-- 方法2:
SELECT e.ename,e.sal,e.deptno FROM `emp` e
WHERE e.sal > ( SELECT MAX(sal) FROM `emp` WHERE deptno = 30 );
-- ANY 查询工资比30部门,其中一个员工高的员工
SELECT e.ename,e.sal,e.deptno FROM `emp` e
WHERE e.sal > ANY ( SELECT sal FROM `emp` WHERE deptno = 30 );
-- 方法2:
SELECT e.ename,e.sal,e.deptno FROM `emp` e
WHERE e.sal > ( SELECT min(sal) FROM `emp` WHERE deptno = 30 );
8.7、EXISTS
exists包含,not exists不包含。
SELECT * FROM A WHERE EXISTS ( SELECT * FROM B WHERE B.id = A.id );
可代替子查询 in
-- 查询入职日期大于1985年的
SELECT * FROM emp
WHERE empno IN ( SELECT empno FROM emp WHERE HIREDATE > TO_DATE( '1985', 'yyyy' ) );
SELECT * FROM emp t1
WHERE EXISTS ( SELECT empno FROM emp WHERE t1.HIREDATE > TO_DATE( '1985', 'yyyy' ) );
9、正则REGEXP
-- ^s 以s开头 | r$ 以r结尾 | . 表示任何一个单字符 | [abc] 包含abc
-- 查询id包含非数字的行
SELECT
( t.AgentID REGEXP '[^0-9.]' ),
t.*
FROM
Call_Info2 t
WHERE
t.StartTime > '2022-02-22 02:59:36'
AND t.HandleFlag = 0
AND ( t.AgentID REGEXP '[^0-9.]' ) = 1
LIMIT 1000;
10、函数
10.1、字符串函数
-- 字符串拼接
concat(列名1,'is a',列名2)
SELECT concat( '1996', '-', '04', '-', '14' ) birthday_date FROM DUAL;
-- 字符串分割符
SELECT CONCAT_WS('-','table','order','details') FROM DUAL
substr(列名,1,4)-- 字符串截取:从第 1 位开始,到后 4 位(不包含)
REPLACE(job,'MANAGER','经理')-- 字符串替换
lcase(列名)、ucase(列名)-- 小写、大写
trim(列名), ltrim(), rtrim()-- 去空格
left(列名,2)--从左边取字符串,取到第2位:
right(列名,2)
length(列名)--字段长度
10.2、时间
CURRENT_DATE()-- 2022-02-24
CURRENT_TIME()-- 02:55:39
CURRENT_TIMESTAMP()-- 2022-02-24 02:56:20
now()
YEAR()
MONTH()
DAY()
-- 查询十分钟内发布的信息
SELECT * FROM mes WHERE DATE_ADD( send_mes, INTERVAL 10 MINUTE ) >= now();
-- 同理date_sub也行
SELECT * FROM mes WHERE DATE_SUB( now( ), INTERVAL 10 MINUTE ) <= send_mes;
interval 10 year -- 后面可以跟year、day、minute、second
-- 类型可以是:date、datetime、timestamp
-- 从今天算活到80岁,还有多少天
SELECT date_add( '1996-4-14', INTERVAL 80 YEAR )FROM DUAL;
-- 19773天
SELECT datediff(date_add('1996-4-14', INTERVAL 80 YEAR), now())FROM DUAL;
-- 查询员工入职满30年
SELECT e.last_name,YEAR ( e.hire_date )
FROM employees e
WHERE YEAR ( now( ) ) - YEAR ( e.hire_date ) >= 30
-- 日期格式的隐式转化 | 只要字符串和日期格式一致就行
SELECT *
FROM employees e
WHERE e.hire_date = '1999-02-07'
-- 时间戳
SELECT FROM_UNIXTIME( 1673112902, '%Y-%m-%d %H:%i:%s' ) FROM DUAL;
-- 转uinx时间戳
SELECT UNIX_TIMESTAMP( '2022-09-13 23:48:22' ) FROM DUAL;
10.3、去重distinct
SELECT只能跟一个字段。
select distinct e.sal from emp e;
11、流程控制
如果为空设置0值。
IFNULL(employees.commission_pct,0)
-- if...else if...else
SELECT
e.last_name,
e.salary,
CASE
WHEN e.salary >= 20000 THEN '牛逼'
WHEN e.salary >= 15000 THEN '腻害'
WHEN e.salary >= 10000 THEN '不错'
WHEN e.salary >= 5000 THEN '行吧'
ELSE '不行啊'
END "工资描述"
FROM
employees e;
-- switch case
SELECT
e.last_name,
e.salary,
e.department_id,
CASE e.department_id
WHEN 10 THEN e.salary * 1.1
WHEN 20 THEN e.salary * 1.2
WHEN 30 THEN e.salary * 1.3
ELSE e.salary * 1.05
END "调薪"
FROM
employees e;
12、死锁
| 死锁 | |
|---|---|
| innoDB | 1、两个以上的线程(事务),双方都在等待对方释放已持有的锁。 2、或者加锁顺序不一样导致循环等待锁释放。 |
| 支持行锁、表锁 | 行锁:只针对当前操作进行加锁。 事务中行锁通过给索引上的索引项加锁实现。 SELECT ... FROM UPDATE 是表锁还是行锁,看WHERE条件是否命中索引。 |
| MyISAM | 不会死锁。 |
报错:Deadlock found when trying to get lock ...
解决:查看正在被锁的事务的trx_id,然后杀死。
select * from INFORMATION_SCHEMA.INNODB_TRX;
kill trx_id;
13、库DB
show databases;
show create database 库名;
-- 字符集:utf8(3个字节)、utf8mb4(英文占用1个字节,一般汉字占用3个字节,emoji表情占4个字节)、gbk
show charset;
-- 排序规则:utf8mb4_general_ci(不区分大小写);utf8mb4_bin(区分大小写,存拼音,日文)
show collation;
-- 创建数据库:create database if not exists 库名
create database if not exists liuxx character set utf8mb4 collate utf8mb4_general_ci;
-- 删除数据库:
drop database if exists 库名
-- 修改数据库:alter database 库名
alter database liuxx character set utf8mb4 collate utf8mb4_general_ci;
14、系统 、用户权限
-- 查询用户登录 user()
select user() from dual;
-- create uesr '用户名'@'允许登录的位置' identified by '密码';
create user zhangsan@'10.0.0.%' identified by '123321';
-- alter user '用户名'@'允许登录的位置' identified by '密码'
alter user zhangsan@'%' identified by '123456';
-- 刷新
flush privileges;
-- drop user '用户名'@'允许登录的位置';
drop user zhangsan@'%';
-- 授权 (给超级用户权限:all *.* '用户名'@'%')
grant all privileges on *.* to lisi@'%' identified by '111111' with grant option;
grant 权限 on 库.表 to 用户 identified by 密码 with grant option;
-- 一般的开发权限:
grant select,update,delete,insert on *.* to wangwu@'10.0.0.%' identified by '123' with grant option;
-- 回收权限:
revoke delete on mydb.* from 'zhangsan'@'10.0.0.%';
-- 查看用户权限:
show grant for 'zhangsan'@'10.0.0.%';