---
title: 20200717 Astro Camp SQL
tags: Astro Camp, SQL
---
# 20200717 Astro Camp SQL
一個資料庫會有很多個表格
像是一個EXCLE有很多分頁
資料庫可以將多個表格互相串連
EXCLE不行
**RDBMS
關聯資料管理系統
Relational DataBase Management Systems**
NoSQL 非關聯式系統
如果只存放資料,不需要做資料中的交叉作用的話,可以用NoSQL
## 建立資料庫
`create database 資料庫名稱;`
## 使用資料庫
`use 資料庫名稱;`
接下來才能在此資料庫裡作查詢
## 表格調整
`alter table`
`change `重新命名
## 刪除資料表
`drop table "資料表名稱"`
DDL/DML/DQL
## 新增資料
`insert into heroes
(name, hero_level, description)
vaule
("琦玉", "C", "任何敵人一拳擊敗");`
一個蘿蔔一個坑,欄位順不重要,有指定就好
沒填入的欄位預設值要看作業系統或欄位型態。
將單引號當字串:在單引號後加上反斜線`"\"`,表示此單引號為純粹的字串,不列入程式語言計算。
eg.
`'speed o'\s sound sonic'`
## 查詢資料
`SELECT * FROM (資料表);`
從特定資料表列出特定資料。
"*"萬用字元
## 過濾資料
`SELECT * FROM (資料表) where 追加條件;`
`SELECT * FROM heroes where hero_level = 's' AND gender ="F";`
用`AND`來連接不同的條件
---
`SELECT name, gender FROM heroes WHERE hero_level = 'S'`
挑出英雄等級為S的名字與性別欄位。
`SELECT * ` 全選欄位,比較占記憶體,效能慢一點。
`SELECT * FROM heroes WHERE age IS null;`
誰沒有填年紀。
### 搜尋關鍵字
`SELECT * FROM heroes WHERE name LIKE '%背心%';`
從英雄資料表中找出名字裡面有背心的英雄。
%代表任意字元
`WHERE name LIKE %背心` 找出XXXX背心的英雄
`WHERE name LIKE 背心%` 找出背心XXXX的英雄
---
### 搜尋兩個條件以上
1.列出10~25歲的英雄
SQL 沒有range 或10..25的語法,所以搜尋10~25歲的人要拆成兩個條件:
`SELECT * FROM heroes WHERE age >= 10 AND age <= 25 ; `
2.列出S級與A級的英雄
`SELECT * FROM heroes WHERE hero_level ='S' OR hero_level = 'A'; `
`AND` 相當於 `&&` 兩個條件都滿足才會被挑出
:::info
推薦寫法:
`SELECT * FROM heroes WHERE hero_level IN ('S', 'A')`
:::
3.列出不是S級的英雄
`SELECT * FROM heroes WHERE hero_level <>'S' `
4.列出不是S也不是A的英雄(可以用`<>'S' AND <>'A'`)
`SELECT * FROM heroes WHERE hero_level NOT IN ('S','A');`
## 更新資料
1.把id為25的英雄年齡更新成10歲
`UPADATE heroes SET age = 10 WHERE id = 25;`
:::info
Rails
`@hero = Hero.find(25)`
`@hero.update(age:10, level:'A')`
:::
2.多重條件
`UPADATE heroes SET age = 10, hero_level = 'A' WHERE id = 25;`
3.所有人老一歲
`UPDATE heroes SET age = age + 1`
因為是大範圍更動(沒有WHERE),MySQL不讓過,要將安全模式關掉,才可以更新。
`SET SQL_SAFE_UPDATES = 0`
*SQLite會過!*
## 刪除資料
因為資料庫無法管控,(git 管控的是資料庫的migration(結構),管不到裡面的資料),所以一般會多加一個欄位is_delete?(boolen)。
當要刪除資料的時候會更改此欄位,將false改成true,以示刪除。
## 計算資料
### 資料總數
計算所有A級英雄總數,並設定成CC的欄位
`select count(*) as CC
FROM heroes
where hero_level = 'A';`
### 加總資料
`SELECT SUM(age)
FROM heroes
WHERE hero_level = 'A' AND IS NOT NULL;`
### 平均資料
`SELECT avg(age)
FROM heroes
WHERE hero_level = 'A' AND IS NOT NULL;`
rails版:
`Hero.average(hero_level:'A').average(:age)`
### 最大值 最小值
`SELECT MAX(age) FROM heroes`
`SELECT MIN(age) FROM heroes`
### 分組
`SELECT hero_level, avg(age)
FROM heroes
GROUP BY hero_level;`
從資料裡面用英雄等級分組(GROUP BY )
並顯示出英雄等級、平均年齡(SELECT hero_level, avg(age))
### 挑調重複的
`select distinct hero_level from heroes`
### 排序
`select * from heroes where hero_level ='S' ORDER BY hero_rank (DESC)`
DESC 反向排序(由大到小)
## 多個資料表查詢
```
SELECT name, danger_level
FROM monster
Where kill_by IN(
select id
from heroes
where name in ('琦玉', '傑諾斯')
)
```
## join 交集 (時間軸:16:20)
```
SELECT monster.name, monster.danger_level, hero.name
FROM monster (left)
LEFT JOIN heroes (right)
ON monster.kill_by = hero.id (ON 後面加上 join 的條件)
WHERE monster.kill_by IS NOT NULL AND hero.hero_level = 'S'
```
`left join` (有點像留住left那一塊的join方式)
當你`from monster`時,`monster`資料庫便是左方的資料庫,`left join`就會以此資料庫為主,`join`進去的資料若無符合 `ON` 條件,便不會被挑選出來。
`right join` 會以右邊的資料庫為主,原來資料庫裡未符合`ON`條件的不會被顯示。
## union