# Ruby(08/14) 五倍紅寶石(第八屆共筆)(2021/8/13)
## Rails-HW
25 mins 內
model: Product
- 商品名稱
- 價錢
- 商品描述
- 是否上架
Product CRUD
- 錄影,可不講解
## Database
寫 Rails 語法時可試著回想資料庫語法是甚麼。
如果要增加或調整資料庫欄位,建議用 Rails 去改不要手動去資料庫調。
文字資料要用引號包起來,數字資料不用。
- 多餘的單引號:
在單引號前面多加一個反斜線\ 是跳脫符號,讓他能正常顯示,不然會被判定為一般引號。
### DDL Data Definition Language
資料定義語言
CREATE 建立資料庫的物件
ALTER 變更資料庫的物件
DROP 刪除資料庫的物件
### DML Data Manipulation Language
資料操作語言
INSERT 新增資料到資料表中
UPDATE 更改資料表中的資料
DELETE 刪除資料表中的資料
### DQL Data Query Language
資料查詢語言
SELECT 選取資料庫中的資料
### DCL Data Control Language
資料控制語言
GRANT 賦予使用者使用權限
REVOKE 取消使用者的使用權限
COMMIT 完成交易作業
ROLLBACK 交易作業異常,將已變動的資料回復到交易開始的狀態
- 追加欄位:
ALTER TABLE heroes
ADD COLUMN super_power VARCHAR(100);
= add_column :heroes, :super_power, :string
- 刪除欄位:
ALTER TABLE heroes
DROP COLUMN super_power;
= remove_column :heroes, :super_power, :string
- 刪除資料表:
DROP TABLE heroes;
= drop_table :heroes
- 新增資料:
INSERT INTO heroes
(name, gender, age, hero_level, hero_rank, description)
VALUES
("竈門炭治郎", "M", 15, "S", 10, 鬼殺隊的一員,為了拯救妹妹,決定要打敗無慘,會使用水之呼吸、日之呼吸以及全集中呼吸。)
可省略欄位名稱不寫,或是只寫部分欄位
- 選取資料:
- 選全部欄位的特定英雄:
SELECT *
FROM heroes
WHERE hero_level = "S" AND gender = "F";
= Hero.where(level: "S",gender = "F")
- 只選特定欄位,做更精準的控制:
把 * 換掉,消耗的記憶體相對比較少
SELECT name, gender
FROM heroes
WHERE hero_level = "S" AND gender = "F";
= Hero.select(:name, :gender).where(level: "S",gender = "F")
- 找到沒有填的欄位:
SELECT *
FROM heroes
WHERE age IS NULL;
- 找特定字元,搜尋名字內有背心的英雄:
SELECT *
FROM heroes
WHERE name LIKE "%背心%";
= Hero.where("name like "%背心%"")
= Hero.where(['name like "%?%"', keyword])
%背心 = xxx背心
背心% = 背心xxx
%背心% = xxx背心xxx
- 找年鄰 10~25之間:
方法一:
SELECT *
FROM heroes
WHERE age >= 10 AND age <=25;
方法二:
SELECT *
FROM heroes
WHERE age BETWEEN 10 AND 25;
= Hero.where("age >= 10 and age <= 25")
= Hero.where("age >= 10")
.where("age <= 25")
= Hero.where(age: 10..25)
- 是 A 跟 S 級的:
方法一:
SELECT *
FROM heroes
WHERE hero_level = "A" OR hero_level = "S";
方法二:
SELECT *
FROM heroes
WHERE hero_level IN ("S", "A");
- 不是 S 級的:
方法一:
SELECT *
FROM heroes
WHERE hero_level NOT IN ("S");
方法二:
SELECT *
FROM heroes
WHERE hero_level<>"S";
- 不是 S 跟 A 級的:
SELECT *
FROM heroes
WHERE hero_level NOT IN ("S", "A");
- 列出所有 A 級男性英雄的姓名以及年齡:
SELECT age , name
FROM heroes
WHERE hero_level IN ("A") AND gender IN ("M");
- 更新資料:
- 把編號 25 號的英雄改成 10 歲
UPDATE heroes
SET age =10
WHERE id = 25;
= Hero.find(25).update(age: 10) (現在用法)
= Hero.find(25).update_attributs(age: 10) (早期用法)
= h = Hero.find(25)
h.age = 25
h.save
記得要加 where 不然會全部改掉
- 刪除資料:
清空資料表內的資料,跟 DROP 不一樣,DROP 是直接刪掉資料庫或資料表
- 刪除 C 級英雄:
DELETE FROM heroes
WHERE hero_level = "C"
- 刪除排名第三的 S 級英雄:
DELETE FROM heroes
WHERE hero_level = "S" AND hero_rank = 3 ;
- 計算總數:
SELECT COUNT(*)
FROM heroes
WHERE hero_level = "A" ;
- 加總:
SELECT SUM(age)
FROM heroes
WHERE hero_level = "A" AND age IS NOT NULL;
= total = Hero.sum(:age)
給資料庫去算就好,不要用 Ruby 轉圈圈算,這是 Ruby 的弱項
- 平均:
SELECT AVG(age)
FROM heroes
WHERE hero_level = "A" AND age IS NOT NULL;
- 最大值:
SELECT MAX(age)
FROM heroes ;
- 最小值:
SELECT MIN(age)
FROM heroes ;
- 分組:
- 計算每個等級英雄的年齡總合
SELECT hero_level, SUM(age) as "總和",AVG(age) as "平均"
FROM heroes
GROUP BY hero_level ;
as 可以改欄位名稱
GROUP BY 是高級版的 DISTINCT
- 有哪些等級:
SELECT DISTINCT hero_level
FROM heroes ;
可應用在下拉選單做分類
- 排序:
- 正向:
SELECT *
FROM heroes
WHERE hero_level = "S"
ORDER BY hero_rank ;
= Hero.where(hero_level: "S").order(:hero_rank)
- 反向:
SELECT *
FROM heroes
WHERE hero_level = "S"
ORDER BY age DESC;
= Hero.where(hero_level: "S").order(hero_rank: :desc)
- 取前三名:
SELECT *
FROM heroes
WHERE hero_level = "S"
ORDER BY hero_rank
LIMIT 3 ;
- 組合技:
- 找出被埼玉打倒的反派
SELECT *
FROM monsters
WHERE kill_by =
(
SELECT id
FROM heroes
WHERE name = "埼玉"
);
- 找出被埼玉跟傑諾斯打倒的反派
SELECT *
FROM monsters
WHERE kill_by IN
(
SELECT id
FROM heroes
WHERE name IN ("埼玉", "傑諾斯")
);
- 主鍵PK:
是某個資料表的一個欄位
每個資料表都要有一個
獨一無二的值
不能是 NULL
- 外部鍵FK:(kill_by)
是某個資料表的一個欄位
參照到另一個欄位的主鍵
用來確認兩個資料表間的資料可以對的起來
不用獨一無二
可以是 NULL
建立外部鍵:(建議要做! 保持資料的完整性,最基本的)
可以用 MySQLWorkbench:圖形介面工具來操作
表格下面有 foreign key 可點選
設定 Referenced
On Update : cascade
On Delete : Restrict
CASCADE: 更新或刪除主鍵的資料時,也更新或刪除外部鍵這邊資料。
SET NULL: 更新或刪除主鍵的資料時,將外部鍵這邊資料設定為 NULL。
RESTRICT: 如果外部鍵這邊有資料,禁止更新或刪除主鍵資料。
NO ACTION: 不做動作(不建議)。
- 交集:
inner / left / right
- Inner Join:兩個都有
- Left Join:左邊為主 + 兩個都有
- Right Join:右邊為主 + 兩個都有
- 把 t2 加到 t1 資料表:
因為沒給他條件,總數會變 t1 * t2
SELECT *
FROM t1
JOIN t2
- Left Join:
以左邊為主,左邊全列出,右邊有的就列,沒有就null:
SELECT *
FROM t1
LEFT JOIN t2
ON t1.username = t2.name ;
- Inner Join:
兩邊都有的才列出:
SELECT *
FROM t1
INNER JOIN t2
ON t1.username = t2.name ;
- 找出被打敗的反派
SELECT m.name, h.name
FROM monsters as m
INNER JOIN heroes as h
ON m.kill_by = h.id
WHERE m.kill_by IS NOT NULL ;
- 找出被 S 級英雄打敗的反派:
SELECT m.name as "反派", h.name as "英雄"
FROM monsters as m
INNER JOIN heroes as h
ON m.kill_by = h.id
WHERE h.hero_level = "S";
= Hero.join(:monsters).where(...)
- ER 模型:
Entity Relationship Model 實體關聯模型
用 MySQLWorkbench 的 Reverse Engineer 可建立
有空可匯入龍哥提供的 MySQL 檔玩玩
### Windows 安裝 SQL
MySQL:有分client、server端
client放windows
server放wsl
## 部屬
Docker:(有機會可以學一下,DevOps 工程師會用到)
一個虛擬化的技術,在原本系統內,虛擬化一個新的作業系統,裡面要安裝什麼系統都可以。
可以用 Docker 開一個貨櫃,整個丟到 server上面,讓每個人都可以直接使用。
解題網站會用到這個技術,就算被別人弄也沒關係,只會把 Docker 的虛擬化系統用壞,不會傷害到自己的系統。
## Rails
- migration檔 : change 方法
change = up + down 的融合版
用 change 建議還是要寫型態,這樣用 rollback 才知道要用什麼型態
不像 up down 有前面的 up 可以做比對
- rails c --sandbox
不會影響到原本資料,只會影響這個空間
- 在 Rails c 裡面打 .all,只會噴 11 筆資料,因為如果全部列出來會太多,使用者根本看不完。
---
[DB XMind](https://www.xmind.net/m/3QwcXi)
---
###### tags: `Ruby` `Rails` `DataBase`