--- 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