[TOC] # CODE JARVIS: 從0開始的自耕碼農生活(二) - 初探 MySQL Notice === 1. SQL 語法中句尾的分號 ; 是必須的,系統完全依賴分號判別語法是否結束,不像 JS 能在大多情況下忽略。 2. SQL 語法中有許多保留字,為了避免命名與保留字衝突,有一派做法習慣將所有命名用 \`\` 包起來,以保證百分之百不會出現衝突問題。 ex: ``` `classmate` ``` DATABASE === ### 創建 Database (CREATE) ``` sql -- CREATE DATABASE 資料庫名稱; CREATE DATABASE `sql_tutorial_company`; ``` ### 顯示 當前 DB server 所有的 database (SHOW) ``` sql -- 注意 DATABASES 最後有個複數 "S" SHOW DATABASES; ``` TABLE === ### 創建表 (CREATE) ``` sql -- CREATE TABLE 表名稱(鍵值對); CREATE TABLE `branch`( `branch_id` INT, `branch_name` VARCHAR(10), `manager_id` INT, PRIMARY KEY(`branch_id`), -- 定義 Primary Key FOREIGN KEY (`manager_id`) REFERENCES `employee`(`emp_id`) ON DELETE SET NULL -- 定義 Foreign Key ); ``` - #### 鍵值對有三種 - Primary Key(主鍵) ~ 用於辨別每筆獨立資料,因此必須是**唯一值** - Attribute(一般屬性) ~ 就一般屬性 - Foreign Key(外部鍵) ~ 關聯其他表的鍵值,因此做關聯時必須在其他表已建立(CREATE)的前提下才能關聯,否則須等關聯的表建立(CREATE)完成後再另行下語法做關聯 ``` sql ALTER TABLE `employee` ADD FOREIGN KEY (`branch_id`) REFERENCES `branch`(`branch_id`) ON DELETE SET NULL; -- 若關聯資料消失,則將鍵值設為 NULL -- 另有 ON DELETE CASCADE; 表示若關聯資料消失,則刪除整筆對應資料 ``` ### 查看表定義 (DESCRIBE) ``` sql -- DESCRIBE 表名; DESCRIBE `employee`; ``` ### 刪除表 (DROP) ``` sql -- DROP TABLE 表名; DROP TABLE `employee`; ``` ### 儲存資料(INSERT) - 預設按照表的定義順序儲存資料 ``` sql -- INSERT INTO 表名 VALUES(值1, 值2, 值3); INSERT INTO `branch` VALUES(1, '研發', NULL); -- 若還沒有對應的外部 key, 先設 NULL, 等對應資料儲存進來後再回頭把 NULL 設回來 ``` - 可自定義儲存資料的順序 ``` sql -- INSERT INTO 表名(屬性2, 屬性3, 屬性1) VALUES(值2, 值3, 值1); INSERT INTO `branch`(`branch_name`, `manager_id`, `branch_id`) VALUES('研發', NULL, 1); ``` ### 更新資料(UPDATE) ``` sql UPDATE `employee` SET `sub_id` = 207 WHERE `emp_id` IN(209, 210); -- 設置條件,類似 JS 的 if ``` ### 查看資料 (SELECT...FROM...) - 全查 ``` sql SELECT * FROM `branch`; ``` - 排序(ASC 正序小到大, DESC 倒序大到小) ``` sql SELECT * FROM `employee` ORDER BY `salary` ASC; ``` - 限制查詢筆數,同時排序 ``` sql SELECT * FROM `employee` ORDER BY `salary` DESC LIMIT 3; -- 結果會是排序過後的前三筆 ``` - 指定查詢鍵值(key) ``` sql SELECT `name` FROM `employee`; ``` - 指定查詢鍵值並去重(duplicate) ``` sql SELECT DISTINCT `sex` FROM `employee`; -- 若同時查詢多個欄位,則必須兩筆資料中的所有欄位的所有值都相同才會視為重複 ``` 聚合函數( Aggregate function ) === - 取得一張表的總筆數 ``` sql SELECT COUNT(*) FROM `employee`; ``` - 取得一張表中指定 key 的總筆數(會忽略NULL) ``` sql SELECT COUNT(`sup_id`) FROM `employee`; ``` - 取得符合條件後的總筆數 (WHERE) ``` sql SELECT COUNT(*) FROM `employee` WHERE `birth_date` > '1970-01-01' AND `sex` = 'F'; ``` > 條件之間可以用 AND、OR 關鍵字 > 設定條件時"不等於"這樣寫: <> > ex: ``` `sex` <> 'F' ``` #### 計算總筆數(COUNT) ```COUNT(*)``` #### 計算平均(AVG) ``` AVG(`salary`) ``` #### 計算總和(SUM) ``` SUM(`salary`) ``` #### 取最大值(MAX) ``` MAX(`salary`) ``` #### 取最小值(MIN) ``` MIN(`salary`) ``` 萬用字元查詢(LIKE) - 多個字元%|一個字元_ === - 取得電話號碼開頭是 123 的客戶 ``` sql SELECT * FROM `client` WHERE `phone` LIKE '123%'; ``` - 取得性艾的客戶 ``` sql SELECT * FROM `client` WHERE `client_name` LIKE '艾%'; ``` - 取得型別是 DATE 時(yyyy-mm-dd),生日在 12 月的員工 ```sql SELECT * FROM `employee` WHERE `birth_date` LIKE '_____12%'; ``` 聯集查詢(UNION) === #### 合併鍵值欄位,合併時型別要一樣;合併多個時數量要一樣; ``` sql SELECT `name` FROM `employee` UNION SELECT `client_name` FROM `client`; ``` ![](https://i.imgur.com/4YY0qUR.png) - 合併多個 ``` sql SELECT `emp_id`, `name` FROM `employee` UNION SELECT `client_id`, `client_name` FROM `client`; ``` ![](https://i.imgur.com/adwoAuu.png) 連接(JOIN) === #### 把兩張表合為一張表,並設置條件來決定兩張表的資料怎樣才算是同一筆 - 取得所有部門經理的 員工id, 名字, 所屬部門名字 ``` sql SELECT `employee`.`emp_id`, `employee`.`name`, `branch`.`branch_name` FROM `employee` JOIN `branch` ON `employee`.`emp_id` = `branch`.`manager_id`; ``` ![](https://i.imgur.com/DiPwQwq.png) #### 關鍵字 RIGHT、LEFT 可以強制指定要完全顯示的那張表(就算不符合) - 取得所有部門經理的 員工id, 名字, 所屬部門名字(包含顯示沒有經理的部門) ``` sql SELECT `employee`.`emp_id`, `employee`.`name`, `branch`.`branch_name` FROM `employee` RIGHT JOIN `branch` ON `employee`.`emp_id` = `branch`.`manager_id`; ``` ![](https://i.imgur.com/Uo1AwUo.png) 子查詢 === - 找出研發部門的經理名字 ``` sql SELECT `name` FROM `employee` WHERE `emp_id` = ( SELECT `manager_id` FROM `branch` WHERE `branch_name` = '研發' ); ``` - 找出對單一位客戶銷售金額超過 50000 的員工名字 ``` sql SELECT `name` FROM `employee` WHERE `emp_id` IN( SELECT `emp_id` FROM `work_with` WHERE `total_sales` > 50000 ); ``` > 用 IN 語法是因為查詢結果可能為一個以上