# 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; #調用存儲過程
```