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