# mysql
* 查询 多表联合查询
* 更新
* 删除
* DCL
* mysql 高级应用
* 优化
## 查询
```
1.select * from 表名;
2.select id,username from 表名;
3.select id,usdername from 表名 where id>5 and id<8;
4.select id,username from 表名 order by age desc,id asc;
5.select id,username from 表名 order by age desc,id asc limit 5;
```
### 查询 - 结果集 区间选择 limit 3,3 从下标为3的位置开始取3条
```
分页
第一页 从 0 开始 取 3条
第二页 从 3 开始 取 3条
第三页 从 6 开始 取 3条
SELECT id,username FROM money limit 6,3;
1 0 3
2 3 3
3 6 3
```
### 统计函数
| 函数 | 说明 |
| ----- | ---------------------------------------- |
| sum | 求和 select SUM(balance) from money; |
| count | 统计总数 select COUNT(id) from money; |
| max | 求最大值 SELECT MAX(age) from money; |
| min | 求最小值 SELECT MIN(balance) from money; |
| avg | 求平均值 SELECT AVG(balance) from money; |
| | |
> https://blog.csdn.net/u011409644/article/details/73611102
### 分组统计
```
mysql> select * from money group by province; #每个省份 出来 一个
+----+--------------+----------+-----------+-----+-----+
| id | username | balance | province | age | sex |
+----+--------------+----------+-----------+-----+-----+
| 8 | 魏缨络 | 7777.13 | 上海 | 29 | 1 |
| 3 | 王思聪 | 99999.99 | 北京 | 30 | 0 |
| 6 | 范冰冰 | 77777.31 | 山东 | 40 | 1 |
| 4 | 刘强东 | 99999.66 | 江苏 | 40 | 0 |
| 5 | 抹茶妹妹 | 77777.66 | 浙江 | 30 | 1 |
| 1 | 泽林兄 | 88888.12 | 辽宁 | 19 | 0 |
| 2 | 秋林兄 | 66666.45 | 黑龙江 | 18 | 0 |
+----+--------------+----------+-----------+-----+-----+
7 rows in set (0.00 sec)
mysql> select * from money group by province with rollup; 了解
+----+--------------+----------+-----------+-----+-----+
| id | username | balance | province | age | sex |
+----+--------------+----------+-----------+-----+-----+
| 8 | 魏缨络 | 7777.13 | 上海 | 29 | 1 |
| 3 | 王思聪 | 99999.99 | 北京 | 30 | 0 |
| 6 | 范冰冰 | 77777.31 | 山东 | 40 | 1 |
| 4 | 刘强东 | 99999.66 | 江苏 | 40 | 0 |
| 5 | 抹茶妹妹 | 77777.66 | 浙江 | 30 | 1 |
| 1 | 泽林兄 | 88888.12 | 辽宁 | 19 | 0 |
| 2 | 秋林兄 | 66666.45 | 黑龙江 | 18 | 0 |
| 2 | 秋林兄 | 66666.45 | NULL | 18 | 0 |
+----+--------------+----------+-----------+-----+-----+
8 rows in set (0.00 sec)
在上面一条sql语句的基础上 统计总数 多了一行
mysql> select count(province),province from money group by province;#统计省份数量以后然后进行分组显示
+-----------------+-----------+
| count(province) | province |
+-----------------+-----------+
| 2 | 上海 |
| 2 | 北京 |
| 2 | 山东 |
| 1 | 江苏 |
| 2 | 浙江 |
| 1 | 辽宁 |
| 1 | 黑龙江 |
+-----------------+-----------+
7 rows in set (0.00 sec)
在分组的基础上统计
mysql> select count(province),province from money group by province with rollup; #了解
+-----------------+-----------+
| count(province) | province |
+-----------------+-----------+
| 2 | 上海 |
| 2 | 北京 |
| 2 | 山东 |
| 1 | 江苏 |
| 2 | 浙江 |
| 1 | 辽宁 |
| 1 | 黑龙江 |
| 11 | NULL |
+-----------------+-----------+
8 rows in set (0.00 sec)
11 是对上面结果的统计
```
### 对统计结果再过滤
```
mysql> select count(province) as result,province from money group by province having result>1;
+--------+----------+
| result | province |
+--------+----------+
| 2 | 上海 |
| 2 | 北京 |
| 2 | 山东 |
| 2 | 浙江 |
+--------+----------+
4 rows in set (0.00 sec)
mysql> select count(province) as result,province from money group by province having result=1;
+--------+-----------+
| result | province |
+--------+-----------+
| 1 | 江苏 |
| 1 | 辽宁 |
| 1 | 黑龙江 |
+--------+-----------+
3 rows in set (0.00 sec)
```
### sql 语句整体使用总结
```
select
[字段1 as 别名,统计函数()],[字段2]
from 表名
where 条件
group by 分组
having 过滤条件
order by 字段
limit 数量 或者 区间
mysql> select id,username as 用户名,province as 省 from money where id>1 and balance >8888 group by province order by id desc limit 3;
+----+--------------+--------+
| id | 用户名 | 省 |
+----+--------------+--------+
| 9 | 薛之谦 | 上海 |
| 6 | 范冰冰 | 山东 |
| 5 | 抹茶妹妹 | 浙江 |
+----+--------------+--------+
3 rows in set (0.00 sec)
```
### 重点 多表联合查询
* 内连接
* 外连接
* 子查询
```
mysql> create table if not exists user(id int(11) unsigned not null primary key auto_increment,username varchar(64) not null,paissword char(64) not null)engine=myisam default charset=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> create table if not exists order_goods(oid int(11) unsigned not null primary key auto_increment,uid int(11) not null,goodsname varchar(64) not null,buytime timestamp)engine=innodb default charset=utf8;
Query OK, 0 rows affected (0.13 sec)
```
#### 内连接
```mysql
第一种写法:
SELECT
u.username as 用户名,
u.id,o.uid,
o.goodsname as 商品名称
FROM
user u,
order_goods o
where
u.id=o.uid;
+--------------+----+-----+-----------------+
| 用户名 | id | uid | 商品名称 |
+--------------+----+-----+-----------------+
| 刘强东 | 1 | 1 | 抹茶 |
| 抹茶妹妹 | 2 | 2 | 帽子 |
| 云翔兄 | 3 | 3 | 小肚肚 |
| 李晨 | 6 | 6 | 苹果三件套 |
| 岳云鹏 | 9 | 9 | 锤子手机 |
| 张继科 | 8 | 8 | 娃娃 |
+--------------+----+-----+-----------------+
6 rows in set (0.00 sec)
第二种写法 inner join on
select 表1.字段[as 别名],表n.字段 from 表1 inner join 表n on 条件;
mysql> select user.id as 用户id,user.username as 用户名,order_goods.goodsname as 商品名称 from user inner join order_goods on user.id=order_goods.uid;
+----------+--------------+-----------------+
| 用户id | 用户名 | 商品名称 |
+----------+--------------+-----------------+
| 1 | 刘强东 | 抹茶 |
| 2 | 抹茶妹妹 | 帽子 |
| 3 | 云翔兄 | 小肚肚 |
| 6 | 李晨 | 苹果三件套 |
| 9 | 岳云鹏 | 锤子手机 |
| 8 | 张继科 | 娃娃 |
+----------+--------------+-----------------+
6 rows in set (0.00 sec)
```
#### 外连接
* 左连接 左边表为准
* 右连接
```
select 表1.字段[as 别名],表n.字段 from 表1 left join 表n on 条件;
mysql> select user.username as 用户名,order_goods.goodsname as 商品名称 from user left join order_goods on user.id=order_goods.uuid;
+--------------+-----------------+
| 用户名 | 商品名称 |
+--------------+-----------------+
| 刘强东 | 抹茶 |
| 抹茶妹妹 | 帽子 |
| 云翔兄 | 小肚肚 | 因为 以左边表为准 会把用户所有信息查出来 买的和没有买的 全显示
| 李晨 | 苹果三件套 |
| 岳云鹏 | 锤子手机 |
| 张继科 | 娃娃 |
| 范冰冰 | NULL |
| 景甜 | NULL |
| 周立泼 | NULL |
+--------------+-----------------+
9 rows in set (0.00 sec)
select 表1.字段[as 别名],表n.字段 from 表1 right join 表n on 条件;
mysql> select user.username as 用户名,order_goods.goodsname as 商品名称 from user right join order_goods on user.id=order_goods..uid;
+--------------+-----------------+
| 用户名 | 商品名称 |
+--------------+-----------------+
| 刘强东 | 抹茶 |
| 抹茶妹妹 | 帽子 | 以右边 表为准 显示订单信息
| 云翔兄 | 小肚肚 |
| 李晨 | 苹果三件套 |
| 岳云鹏 | 锤子手机 |
| 张继科 | 娃娃 |
+--------------+-----------------+
6 rows in set (0.00 sec)
```
#### 子查询 in
```
mysql> select uid from order_goods; //看看 谁买了东西
+-----+
| uid |
+-----+
| 1 |
| 2 |
| 3 |
| 6 |
| 9 |
| 8 |
+-----+
6 rows in set (0.00 sec)
mysql> select * from user where id in(1,2,3,6,9,8); 然后 带着上面的结果 查看 详细信息
+----+--------------+----------+
| id | username | password |
+----+--------------+----------+
| 1 | 刘强东 | 123321 |
| 2 | 抹茶妹妹 | 123123 |
| 3 | 云翔兄 | 1234331 |
| 6 | 李晨 | 123432 |
| 8 | 张继科 | 122222 |
| 9 | 岳云鹏 | 12222 |
+----+--------------+----------+
6 rows in set (0.00 sec)
上面的整合 :
mysql> select username as '用户名' from user where id in(select uid from order_goods);
+--------------+
| 用户名 |
+--------------+
| 刘强东 |
| 抹茶妹妹 |
| 云翔兄 |
| 李晨 |
| 岳云鹏 |
| 张继科 |
+--------------+
6 rows in set (0.00 sec)
```
#### 联合查询 将结果合并在一起显示
union
union all
```
mysql> select id from user union select uid from order_goods;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+----+
9 rows in set (0.00 sec)
mysql> select id from user union all select uid from order_goods;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 1 |
| 2 |
| 3 |
| 6 |
| 9 |
| 8 |
+----+
15 rows in set (0.00 sec)
综上 union 将 union all 中的结果 去除重复记录
```
## 数据更新 update
```
update 表名 set 字段1=值1,字段2=值2,字段3=值3 where 条件;
update money set balance=100,sex=1 where id>2 and id<5;
update money set balance=balance-100 where id>2 and id<5;
```
#### 两个表的记录同时更新
```
mysql> update money m,user u set m.balance=m.balance*u.age where m.id=u.id;
Query OK, 9 rows affected (0.00 sec)
Rows matched: 9 Changed: 9 Warnings: 0
```
### 删除记录 delete
```
delete from 表名 where 条件;
mysql> delete from test; 不加where 条件表示 清空所有数据库
Query OK, 1 row affected (0.00 sec)
注意: delete from 表名 清空的时候 再插入数据 id从原来的 往后累加
mysql> delete from money where username='王思聪' or id=10;
Query OK, 2 rows affected (0.17 sec)
truncate table 表名;
清空表内容 下一次插入 id 还是从1 开始
```
## DCL语句
#### 创建数据库用户
```
grant all on *.* to root@'%' identified by '你的数据库密码' with grant option;
授权 可以远程 用 root 连接到 数据库服务器
all 代表的是权限 update select insert delete all
*.* 第一个 * 代表所有的数据库 第二个* 代表所有的表
root 代表用户
% 代表所有的 ip地址
identified by 跟 密码
flush privileges;
mysql> grant select,insert on python1806.money to 'zelinx'@'localhost' identified by '123321';
Query OK, 0 rows affected, 1 warning (0.07 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
移除权限 --------------------------------------------------
revoke 权限 on 数据库.数据表 from 用户@'主机地址'
mysql> revoke insert on python1806.money from 'zelinx'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
```
## mysql 主从
> 如何减轻 数据的压力 方案 读写分离 实线方案:主从复制
| IP地址 | 角色 |
| ------------ | --------------- |
| 10.11.53.95 | master 主 写 |
| 10.11.53.172 | slave 从 读 |
> 准备工作 都安装好mysql
>
> 关闭防火墙 sudo ufw disable
1.到主服务器上进行配置
```
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
85 server-id = 95 #IP地址的最后一位
86 log_bin = /var/log/mysql/mysql-bin.log #binlog日志的存放路径
87 expire_logs_days = 10
88 max_binlog_size = 100M
89 binlog_do_db = kangbazi #同步的数据库 名称
90 binlog_ignore_db = mysql #忽略的数据库名称
mysql 是每个数据库 特有的 好比身份证号 不能进行同步
```
2.到从服务器上进行配置
```
84 server-id = 172 #ip地址最后一位
85 #log_bin = /var/log/mysql/mysql-bin.log
86 expire_logs_days = 10
87 max_binlog_size = 100M
90 replicate_do_db = kangbazi #同步的数据库
91 replicate_ignore_db = mysql #忽略的数据库
```
3.主从创建一模一样的数据库 及表结构
```
mysql> create database kangbazi;
mysql> show databases;
mysql> use kangbazi;
mysql> create table if not exists user(id int(11) unsigned not null primary key auto_increment,username varchar(64) not null)engine=innodb default charset=utf8;
```
4.到主数据库上 设置一个专门用来同步权限的账户
```
mysql> create user 'user'@'X.X.X.X' identified by 'password';
mysql> grant replication slave on *.* to 'qulinx'@'%' identified by '654321';
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1176 | kangbazi | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
先不要关闭窗口 先不要重启 mysql
```
5.到从服务器上进行配置
```
? change master to
mysql> change master to
-> MASTER_HOST='10.11.53.95',
-> MASTER_USER='qulinx',
-> MASTER_PASSWORD='654321',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=1176,
-> MASTER_CONNECT_RETRY=10;
开启从服务器
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
查看从服务器的状态
mysql> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
看到 说明成功
```
## 表结构 表数据的复制
```
mysql> create table t1 like user; #复制表结构
mysql> insert into t1 select * from user; #复制内容
```
## mysql 视图
```
select * from t1 where id>2 and id <10; #经常查询这个范围的 内容
每次这么查询 很耗资源
解决方案 把这个区间的内容 放到临时表中 下一次直接来这个表中 拿
? view
mysql> create view v_t1 as select * from t1 where id>2 and id<10;
mysql> show tables;
+-----------------+
| Tables_in_day17 |
+-----------------+
| t1 | |
| v_t1 | 多了一个临时表
+-----------------+
6 rows in set (0.00 sec)
mysql> select * from v_t1;
因为 v_t1 是依托于 t1 表存在 删除t1表 临时表 v_t1 也不能用
恢复表t1 v_t1 也恢复
drop view v_t1;
mysql> show create view v_t1\G 显示查看的过程
```
## mysql 内置函数
```
字符串函数
mysql> select concat("kangbazi","1806") as 名字;
+--------------+
| 名字 |
+--------------+
| kangbazi1806 |
+--------------+
mysql> select ucase('mysql');
mysql> select lcase('MYSQL');
select length("我很怕你啊"); 一个汉字占三个
mysql> select ltrim(" 为什么啊");#去除左侧空格
mysql> select rtrim(" 因为我怕老婆啊 ");去除右侧空格
mysql> select repeat('linux',3);
+-------------------+
| repeat('linux',3) |
+-------------------+
| linuxlinuxlinux |
+-------------------+
mysql> select replace("java是世界上最好的语言","java","python");
将java 替换成 Python
mysql> select substr("python is so coole",2,4); 从下标为2开始截取4个
#mysql 下标从1开始
mysql> select concat(space(20),"kangbazi");
数学函数
mysql> select bin(10); 将10转成2进制
select ceiling(10.1);#11
select floor(10.1)#10
mysql> select rand(); 随机数
日期函数
mysql> select now(); 当前时间
select week(now());#返回当前时间是第几周 35
select year(now()); #2018
mysql> select datediff("2018-9-5","2019-10-5"); 计算两个日期之间的差额
```
## 预处理 防sql注入 用到 预处理
```
select * from money where id>2;
select * from money where id>10;
select * from money where id>?;
mysql> prepare yuchuli from "select * from t1 where id>?";
mysql> set @a=2;
mysql> execute yuchuli using @a;
以上就是相当于 执行 select * from t1 where id>2;
```
## mysql 存储
> 在开发过程中 经常需要批量往数据库中插入记录
>
> 存储就好比是 存储代码段 也就是函数 实线批量插入
```
\d // #更改结束符 以 //结束
mysql> create procedure inserts() begin set @i=1; while @i<=1000 do insert into t3(name) values(concat('user',@i)); set @i=@i+1; end while; end//
\d ; #改回;结束符
类似于函数 不调用不执行
show procedure status;
mysql> show create procedure inserts\G 显示存储创建过程
call inserts; #调用存储过程
```