# [筆記] MySQL 基礎 ### 基本介紹 #### 什麼是 Database ![](https://i.imgur.com/ZYaxYeK.png) * DBMS 為向 Database 存取的訪問接口 * 通常稱 DBMS + Database 為 Database,EX : MySQL、Oracle、MongoDB...等等 #### SQL 與 NoSQL * 區別在於有沒有使用 SQL 語言,NoSQL 的資料儲存可以不需要固定的表格模式 * SQL : MySQL、Oracle...等等 * NoSQL : MongoDB...等等 ### 安裝 Window : * 建議用 Installer 下載安裝 : [MySQL Installer 5.7.26](https://dev.mysql.com/downloads/windows/installer/5.7.html) **中間跳過的步驟默認就好** ![](https://i.imgur.com/wuWpNry.png) * 建議選擇 Developer Default ![](https://i.imgur.com/CcbMwYt.png) * 這步檢查依賴,`Execute` 就好 ![](https://i.imgur.com/uPpWiDu.png) * 這邊設定密碼 ![](https://i.imgur.com/IcsLgw7.png) * 這邊輸入剛剛設定的密碼,點擊 `Check` ![](https://i.imgur.com/twA25Yx.png) * 之後在這裡進行操作,輸入剛剛設定的密碼 **P.S.後來在另一台電腦一直無法安裝,有閃退的情況,後來安裝 8.0.16 就正常了** macOS : * 下載地址 : [MySQL 官網 - MySQL Community Server 5.7](https://dev.mysql.com/downloads/mysql/5.7.html#downloads) ### Database 與 Table * Database 是由很多 Table 組成的 * Table 存放資料,且是有結構的 #### Database 基本操作 * `show databases;` : 顯示目前有哪些 Database * `create database <name>;` : 創建 Database * `drop database <name>;` : 刪除 Database * `use <database name>;` : 切換 Database * `select database();` : 查看目前正在使用的是哪個 Database * `delimiter <結束符號>` : 預設結束符號是 `;`,這行命令可以做修改 ( 不建議 ) * `show warnings;` : 查看錯誤訊息 **SQL 大小寫都可運行,建議關鍵字大寫** #### Table ![](https://i.imgur.com/1I7Ew2d.png) * column : 行,相同的資料類型 * row : 列,一筆一筆的數據 #### Table Data Type 有三種大分類 : Numeric、String、Date * [資料類型官方文檔](https://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html) #### Table 的創建 ```sql= CREATE TABLE person ( name VARCHAR(20), phone VARCHAR(20), age INT ); ``` #### Table 基本操作 * `show tables` : 顯示目前有哪些 Table * `show columns from <table name>` : 顯示 Table 的每個 columns * `desc <table name>` : 描述 Table 的資訊 ( 顯示跟上面的命令一樣,可以用這條命令就好 ) ![](https://i.imgur.com/sxToAEH.png) * `drop table <table name>` : 刪除 Table ### Data Insert #### 如何插入資料 ```sql= insert into <table_name>(<column1_name>, <column2_name>) values(<column1_data>, <column2_data>), (<column1_data>, <column2_data>); ``` #### 查看資料 ```sql= SELECT * from <table_name>; ``` * 查看 Table 裡的所有資料 ```sql= SELECT <column_name> from <table_name>; ``` * 查看 Table 裡某個 column 的所有資料 #### 創建特殊要求的 Table * NULL 和 NOT NULL : * NULL 默認為 YES * 創建時 `<column name> <data type> NOT NULL`,NULL 就會變 NO * **插入資料時,NULL 為 NO 的資料不能為空** * Default Value : * Default 默認為 NULL * 創建時 `<column name> DEFAULT <value>` * PRIMARY KEY : * 唯一性,不能重複,不可 NULL * 創建時 `<column name> <data type> PRIMARY KEY` * 如果需要兩個以上 PRIMARY KEY,可以設置聯合 PRIMARY KEY * 聯合 PRIMARY KEY : `PRIMARY KEY(<column1 name>, <column2 name>)` * UNIQUE : * 唯一性,不能重複,可 NULL * 創建時 `<column name> <data type> UNIQUE` * AUTO_INCREMENT : * 設置時,必須同時是個 Key * 創建時 `<column name> <data type> <PRIMARY KEY or UNIQUE> AUTO_INCREMENT` ,常用在 ID 之類,不填值時會累加 ### CRUD 基本的增刪改查 * Create * Read * Update * Delete #### 使用 SQL 文件 Create * 創建一個使用 SQL 語法的文件 `test.sql` * `source <SQL 文件路徑 EX : /Users/user/SQL-training/test.sql>;` 注意分隔要 `/` ```sql= CREATE TABLE IF NOT EXISTS person ( name VARCHAR(20), phone VARCHAR(20), age INT ); ``` * `IF NOT EXISTS` 可以在創建 Table 時,查看 Table 是否存在,不存在就創建,存在則否 #### Read ```sql= SELECT <column_name> as <別名> from <table_name>; ``` * column 的名稱會以別名顯示 ```sql= SELECT * from <table_name> WHERE <column1_name> = "想找到的資料" <AND 或 OR> <NOT> <column2_name> = "想找到的資料"; ``` * WHERE 像是 if,可以過濾 #### Update ```sql= UPDATE <table_name> set <column_name> = "想改成這個資料" WHERE ...; ``` * 通常會加上 WHERE 來過濾要改的資料 * 較安全步驟為 1. 先 SELECT + WHERE 找出想改的資料 2. 再來 UPDATE + 剛剛的 WHERE 來更動 #### Delete ```sql= DELETE from <table_name> WHERE ...; ``` * 跟 UPDATE 一樣通常加上 WHERE 過濾 * 跟 UPDATE 一樣,先 SELECT + WHERE 較安全 ### SQL 字串相關處理方法 #### 拼接 CONCAT * CONCAT : ```sql= SELECT CONCAT(<column1_name>, <column2_name>) as <別名> from <table_name>; ``` * 輸出會是 `<column1_name><column2_name>` * CONCAT_WS : ```sql= SELECT CONCAT_WS("<間格符>", <column1_name>, <column2_name>, <column3_name>) as <別名> from <table_name>; ``` * 輸出會是 `<column1_name><間格符><column2_name><間格符><column2_name>` #### 剪輯 SUBSTRING、REPLACE * SUBSTRING : * `SUBSTRING("Hello World", 7)` : 從前面數,輸出為 `World` * `SUBSTRING("Hello World", -3)` : 從後面數,輸出為 `rld` * `SUBSTRING("Hello World", 1, 4)` : 第 n 個到第 m 個,輸出為 `Hell` * REPLACE : * `REPLACE("Hello World", "World", "MySQL")` : 替換,輸出為 `Hello MySQL` #### 反轉 REVERSE * `REVERSE("Hello World")` : 反轉,輸出為 `dlroW olleH` #### 長度 CHAR_LENGTH * `CHAR_LENGTH("Hello World")` : 字串長度,輸出為 `11` #### 大小寫 LOWER、UPPER * `LOWER("Hello World")` : 轉小寫 * `UPPER("Hello World")` : 轉大寫 * 數字符號都不會變 ### SELECT 進階 #### 按規則排序 ORDER BY ```sql= SELECT * from <table_name> ORDER BY <column_name>; ``` * 會按照 `column_name` 進行升序排序 * 如要進行降序排序 : `ORDER BY <column_name> desc` * 字母、日期也可排序 ```sql= SELECT <column1_name>, <column2_name>, <column3_name> from <table_name> ORDER BY 3, 1; ``` * 按照 `column3_name` 與 `column1_name` 進行排序 * 如果 `column3_name` 相同才按照 `column1_name` 排序 #### 限制搜尋資料顯示的資料數目 LIMIT ```sql= SELECT * from <table_name> ORDER BY <column_name> LIMIT 3; ``` * 顯示排序後前三個 * `LIMIT 2, 4` : 顯示從 2 開始後 4 筆資料 * `LIMIT 2, 18446744073709551615` : 顯示從 2 開始後的所有資料 #### 模糊搜尋 LIKE ```sql= SELECT * from <table_name> WHERE <column_name> LIKE "%i%"; ``` * 顯示包含 `i` 的 * `%` 代表任意字符 * `_` 代表一個任意字符 * 如果要找的資料包含 `%` 或 `_`,可以寫成 `\%` 和 `\_` * SQL 裡搜尋是不區分大小寫的,如要區分需要額外設置 ### 資料聚合處理 #### 計數 COUNT ```sql= SELECT COUNT(*) from <table_name>; ``` * 計算資料數量 #### 統計唯一值 DISTINCT ```sql= SELECT DISTINCT <column_name> from <table_name>; ``` * 將 `column_name` 內重複的資料去除後顯示出來 #### 資料整合 GROUP BY ```sql= SELECT COUNT(<column_name>) from <table_name> GROUP BY <想合併的 column_name>; ``` * 將 `想合併的 column_name` 分組後算出每組 `column_name` 的資料數量 #### 最大值與最小值 MAX、MIN * `MAX(<column_name>)` : `column_name` 的最大值 * `MIN(<column_name>)` : `column_name` 的最小值 #### 和與平均值 SUM、AVG * `SUM(<column_name>)` : `column_name` 的和 * `AVG(<column_name>)` : `column_name` 的平均值 #### HAVING `WHERE` 只能對原始資料過濾,假如要對 `GROUP BY` 之後的資料過濾就要用到 `HAVING` ```sql= SELECT COUNT(<column_name>) from <table_name> GROUP BY <想合併的 column_name> HAVING <column1_name> = "想找到的資料"; ``` ### Data Type 詳細介紹 #### 數值類型 * 整數 ( Integer ) - 準確的 * 標準類型 : * INTEGER ( INT ) * SMALLINT * 擴充類型 : * TINYINT * MEDIUMINT * BIGINT * 後面加 `UNSIGNED` 表示為無負號 * 定點數 ( Fixed-Point ) - 準確的 * DECIMAL ( 用於金錢 ) * `DECIMAL(m, d)` : * 總共 m 位,小數點後 d 位 * 小數點後不足補 0,多的四捨五入 * 可負數,不算位數 * NUMERIC : 跟 DECIMAL 是一樣的 * 浮點數 ( Floating-Point ) - 不準確的 * FLOAT * `FLOAT(m, d)` : * 總共 m 位,小數點後 d 位 * DOUBLE : 用法跟 FLOAT 是一樣的,差別在於 DOUBLE 可存字節較多 * 位 ( Bit-Value ) * BIT * `BIT(m)` : * 總共 m 位 * m 最小 1,最大 64,默認為 1 * 插入方法 : ```sql= insert into <table_name> values(b'1010') ``` * 純數字為十進位 * `b'1010'` 為二進位 * 顯示方法 : ```sql= SELECT <column_name>+0 from <table_name> ``` * `<column_name>+0` : 顯示十進位數值 * `bin(<column_name>+0)` : 顯示二進位數值 * `oct(<column_name>+0)` : 顯示八進位數值 * `hex(<column_name>+0)` : 顯示十六進位數值 * [數值類型的官方文件](https://dev.mysql.com/doc/refman/5.7/en/numeric-types.html) #### 時間類型 * DATE * 日期 ( YYYY-MM-DD ) * 範圍 : `1000-01-01` ~ `9999-12-31` * 可插入 INT 型 `20181001`,也可不需 `-` `"20181001"`,但不可缺少年月日 * TIME * 時間 ( HH:MM:SS ) * 範圍 : `-838:59:59` ~ `838:59:59`,小時範圍那麼大的原因是,也可以表示時間差 * 插入規則同 DATE,但可缺少時分秒 * `12:10` 為 `12:10:00` * `1210` 為 `00:12:10` * `10` 為 `00:00:10` * YEAR * 年,為四個字符 * 範圍 : `1901` ~ `2155` * 插入兩位 INT : * `1` ~ `69` 為 `2001` ~ `2069` * `70` ~ `99` 為 `1970` ~ `1999` * `0` 為 `0000` * 插入兩位 STRING : * `"0"` ~ `"69"` 為 `2000` ~ `2069` * `"70"` ~ `"99"` 為 `1970` ~ `1999` * DATETIME * 日期 + 時間 ( YYYY-MM-DD HH:MM:SS ) * 範圍 : `1000-01-01 00:00:00` ~ `9999-12-31 23:59:59` * TIMESTAMP * 範圍 : `"1970-01-01 00:00:01" UTC` ~ `"2038-01-19 03:14:07" UTC` * 會隨著 timezone 改變 * 默認當前時間 * `SELECT NOW()` : 查看系統當前時間 * 以下兩條程式碼是相同功能的 ```sql= CREATE TABLE <table_name>(<column_name> TIMESTAMP) CREATE TABLE <table_name>(<column_name> TIMESTAMP DEFAULT NOW() ON UPDATE NOW()) ``` * timezone * `show variables LIKE "%time_zone%"` : 查看包含 time_zone 字串的變量 * `SET time_zone = "-12:00"` : 更改 time_zone,根據 UTC 時間減 12 小時 * `SET time_zone = "system"` : 更改 time_zone 為系統當前時區 * time_zone 也可用國家名稱下去設置 * [時間類型的官方文件](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-type-overview.html) * [時間與日期函式](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html) #### 字符串類型 * CHAR 與 VARCHAR * 後面帶的數字代表字串長度 * CHAR : 適用於固定長度 * 較不省空間 * VARCHAR : 適用於不固定長度 * 更新效率較慢,不如 CHAR * 平常會多 1 bytes 儲存字串長度 * BINARY 與 VARBINARY * 後面帶的數字代表 bytes 長度 * BINARY : 適用於固定長度 * 較不省空間 * 插入的字串不足會補上 `\0` * VARBINARY : 適用於不固定長度 * 更新效率較慢,不如 BINARY * BLOB 與 TEXT * 適用於儲存文章 * BLOB : 較大的 BINARY * TEXT : 較大的 CHAR * `SET max_sort_length = n` : 設置此變量後,排序時只對前 n 個字符排序 * ENUM * 給予特定字串選擇 `ENUM("F", "M")` * 類似單選 * SET * 跟 ENUM 很像,也是一個 list * 但 SET 可以選擇一個集合 * 類似複選 * [字符串類型的官方文件](https://dev.mysql.com/doc/refman/5.7/en/string-types.html) #### 對已經定義好的 Table ,更改 Column 的資料類型 ```sql= ALTER TABLE <table_name> MODIFY <column_name> <想更改成的資料類型> ``` * 禁止 varchar 改成 int * 修改資料類型前一定要備份 ### SQL 邏輯操作符 #### EQUAL 與 NOT EQUAL * EQUAL : `<column_name> = 3000` * NOT EQUAL : `<column_name> != 3000` 或 `NOT <column_name> = 3000` #### LIKE 與 NOT LIKE * 模糊搜尋 #### GREATER THAN 與 LESS THAN * GREATER THAN : `<column_name> > 3000` * LESS THAN : `<column_name> < 3000` * 包含 : `>=`、`<=` #### AND 與 OR * AND : 條件都要滿足 * OR : 條件只要滿足一項 #### BETWEEN * `<column_name> BETWEEN 1000 and 3000` #### IN 與 NOT IN * 搜尋 list 裡面有的值 * IN : `<column_name> IN (5000, 6000, 7000, 8000)` * NOT IN : ``<column_name> NOT IN (5000, 6000, 7000, 8000)`` #### CASE STATEMENT ```sql= SELECT <column_name>, case when <column_name> >= 7000 then "high" else "low" end as <別名> from <table_name>; ``` ### MySQL 內建函式 #### 數值處理函式 * CEIL * FLOOR * DIV : 整數除法 * MOD * POWER * ROUND :四捨五入 #### 日期時間函式 * NOW * CURDATE : 當前日期 * CURTIME : 當前時間 * DATE_FORMAT * DATE_ADD : 時間加減 * DATEDIFF : 求時間差 #### 字串處理函式 * CONCAT * CONCAT_WS * LOWER * UPPER * LEFT : 擷取頭 * RIGHT : 擷取尾 * LENGTH * LTRIM : 去頭 * RTRIM : 去尾 * TRIM : 去頭去尾 * REPLACE * SUBSTRING #### 信息函式 * CONNECTION_ID : 當前與 MySQL 連線的 ID * DATABASE : 當前使用的 database * LAST_INSERT_ID : 最後插入資料的資料 ID * USER : 當前用戶 * VERSION #### 聚合函式 * AVG * COUNT * MAX * MIN * SUM #### 加密函式 * MD5 : 用來存取密碼 * PASSSWORD : 通常用於修改 MySQL 密碼 `SET PASSSWORD = PASSSWORD('ABC123')` ### 關聯 ( 一對多 ) #### 通過 ID 關聯兩個 Table ```sql= CREATE TABLE customers( id INT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(100), last_name VARCHAR(100), email VARCHAR(100) ); INSERT INTO customers(first_name, last_name, email) VALUES ('Robin', 'Jackman', 'roj@gmail.com'), ('Taylor', 'Edward', 'taed@gmail.com'), ('Vivian', 'Dickens', 'vidi@gmail.com'), ('Harley', 'Gilbert', 'hgi@gmail.com'); CREATE TABLE orders( id INT AUTO_INCREMENT PRIMARY KEY, order_date DATE, amount DECIMAL(8,2), customer_id INT ); INSERT INTO orders(order_date, amount, customer_id) VALUES ('2001-10-12', 99.12, 1), ('2001-09-21', 110.99, 2), ('2001-10-13', 12.19, 1), ('2001-11-29', 88.09, 3), ('2001-11-11', 205.01, 4); ``` * 這邊有兩張 Table,客戶訊息與訂單訊息,訂單訊息以 `customer_id` 與客戶訊息的 `id` 做關聯 ```sql= SELECT * from orders WHERE customer_id = (SELECT id from customers WHERE email = "roj@gmail.com"); ``` * 查找 Robin Jackman 的訂單 #### 使用 FOREIGN KEY 約束關聯字段 ```sql= FOREIGN KEY (customer_id) REFERRENCES customers(id) ``` * 在創建 Table 時,加上這段可以約束訂單訊息的 `customer_id` 與客戶訊息的 `id` #### 關聯表的操作 **使用 JOIN 合併關聯表** ![](https://i.imgur.com/VgX1FUb.png) * INNER JOIN : 顯示出有關聯的所有資料 ( 沒關聯的不會顯示 ) ```sql= SELECT * from customers INNER JOIN orders WHERE customers.id = orders.customer_id; ``` `WHERE` 可改成 `ON` * LEFT JOIN : 顯示出所有 SELECT 的 Table 以及他們的關聯資料 ```sql= SELECT * from customers LEFT JOIN orders WHERE customers.id = orders.customer_id; ``` `IFNULL(SUM(amount), 0)` : 如果值為 NULL 則顯示 0 * RIGHT JOIN : 顯示出所有 JOIN 的 Table 以及他們的關聯資料 ```sql= SELECT * from customers RIGHT JOIN orders WHERE customers.id = orders.customer_id; ``` * ON DELETE : 在刪除被參照的 Table 內資料時,也一起刪除其他 Table 參照此 Table 的相關資料 ```sql= ON DELETE CASCADE ``` * 在創建 Table 時,除了 FOREIGN KEY,另外加上這段 ### 關聯 ( 多對多 ) **兩張多對多的 Table 會有一張 Table 把他們關聯起來** ![](https://i.imgur.com/EbgXtpe.png) * books 與 reviewer 為多對多 ### MySQL 存入中文,編碼問題 #### Window * 指令同下 * 但因為 `MySQL 5.7 Command Line Client` 不支援中文,所以必須以其他方式插入中文資料 * `MySQL Workbench`、`VS code` 都可以 #### Mac ```sql= CREATE database <database_name> DEFAULT CHARSET = utf8 COLLATE = utf8_general_ci; ``` * 創建資料庫時修改默認編碼 ```sql= ALTER database <database_name> CHARSET = utf8 COLLATE = utf8_general_ci; ``` * 已存在的 database 修改默認編碼 ```sql= ALTER table <table_name> CONVERT TO CHARACTER SET utf8; ``` * 若是修改了已存在的 database,其本身已存在 table,必須一併更改默認編碼 ###### tags: `筆記` `程式語言` `SQL` `資料庫` `MySQL`