【史上最全MYSQL總結】MySQL超詳細筆記
本文主要介紹了mysql是個啥、他的分類、SQL命令,MySQL的安裝注意事項、分類以及在MySQL中常用的命令,包括:資料查詢(基本查詢、排序查詢、條件查詢、時間查詢、字串查詢、聚合函式、分組查詢、分組過濾、限定查詢、子查詢、合并查詢、表連接查詢)、DML操作(增刪改)、庫表操作、約束、事務、權限管理、視圖等等;
文章目錄
- 【史上最全MYSQL總結】MySQL超詳細筆記
- 1、寫在前面
- 2、 資料庫的引入
- 2.1、資料庫是個啥?
- 2.2 資料庫的分類
- 3、資料庫管理系統
- 常見的資料庫管理系統
- 4、MySQL
- 4.1、訪問與下載
- 4.2、安裝時的注意事項
- 4.3、 MySQL的目錄結構
- 4.4、MySQL組態檔
- 5、 SQL簡介
- 5.1、查看MySQL中所有資料庫
- 5.2、創建自定義資料庫
- 5.3、洗掉資料庫
- 5.4、查看資料庫創建資訊
- 5.5、修改資料庫
- 5.6、使用資料庫
- 5.7、查看當前使用的資料庫
- 6、客戶端工具
- 6.1 Navicat
- 6.2 SQLyog
- 6.3 DataGrip(Idea開發工具集成)
- 7、 SQL語言分類
- 8、 資料查詢
- 8.1 資料表的基本結構
- 8.2、基本查詢
- 8.2.1、查詢所有列
- 8.2.2 、查詢部分列
- 8.2.3 、對列中的資料進行運算
- 8.2.4 、列的別名
- 8.2.5、 查詢結果去重
- 8.3 、排序查詢
- 8.3.1、依據單列進行排序
- 8.3.2 、依據多列進行排序
- 8.4 、條件查詢
- 8.4.1 、等值判斷(=)
- 8.4.2、不等值判斷(>、<、>=、<=、!=、<>)
- 8.4.3、邏輯判斷(and、or、not)
- 8.4.4 、區間判斷(between and)
- 8.4.5 、NULL值判斷(IS NULL、IS NOT NULL)
- 8.4.6 、列舉查詢(IN (值1,值2,值n....))
- 8.4.7、 模糊查詢(_、%)
- 8.4.8 、分支結構查詢
- 8.5、 時間查詢
- 8.6 、字串查詢
- 8.7、聚合函式
- 8.7.1 、求總行數
- 8.7.2、單列總和
- 8.7.3、單列平均值
- 8.7.4、單列最大值
- 8.7.5 、單列最小值
- 8.8、分組查詢
- 8.8.1、查詢各部門的總人數
- 8.8.2、查詢各部門的平均工資
- 8.8.3、查詢各個部門、各個崗位的人數
- 8.8.4、常見問題
- 8.9 、分組過濾查詢
- 8.9.1、 統計部門中的最高工資
- 8.10、限定查詢
- 8.10.1、查詢前5行記錄
- 8.10.2 、查詢范圍記錄
- 8.11、查詢總結
- 8.11.1 、SQL陳述句撰寫順序
- 8.11.2、SQL陳述句執行順序
- 8.12、子查詢(作為條件判斷)
- 8.12.1、查詢工資大于Bruce的員工資訊
- 8.13、子查詢(作為列舉查詢的條件)
- 8.13.1、查詢與King同一部門員工資訊
- 8.13.2、工資高于部門編號為60的所有人的資訊
- 8.14、子查詢(作為一張表)
- 8.14.1 、查詢表中部分列的資訊,獲得工資大于15000的
- 8.15、合并查詢
- 8.15.1、合并兩張表的結果(去除重復記錄)
- 8.15.2 、合并兩張表的結果(保留重復記錄)
- 8.16、表連接查詢
- 8.16.1、內連接查詢(INNER JOIN ON)
- 8.16.2 、內連接查詢
- 8.16.3、三表連接查詢
- 8.16.4、多表連接查詢
- 8.16.5、左外連接查詢(LEFT JOIN ON)
- 8.16.6、右外連接查詢(RIGHT JOIN ON)
- 9、 DML操作(增、刪、改)
- 9.1、新增(INSERT)
- 9.2、修改(UPDATE)
- 9.3、洗掉
- 9.4、清空(TRUNCATE)
- 10、庫表操作
- 10.1、資料庫創建(CREATE)
- 10.2、修改資料庫
- 10.2.1、修改資料庫的字符集
- 10.3 洗掉資料庫
- 10.4、資料型別
- 10.4.1 、數值型別
- 10.4.2 、日期型別
- 10.4.3、字串型別
- 10.5、資料表的創建(CREATE)
- 11、約束
- 11.1、物體完整性約束
- 11.1.1 、主鍵約束
- 11.1.2、唯一約束
- 11.1.3、自動增長列
- 11.2、域完整性約束
- 11.2.1、非空約束
- 11.2.2、默認值約束
- 11.2.3 、參考完整性約束
- 11.3、約束創建整合
- 11.3.1 、創建Grade表
- 11.3.2、創建Student表
- 11.4、資料表的修改(ALTER)
- 11.4.1、向現有表中添加列
- 11.4.2 、修改表中的列
- 11.4.3、洗掉表中的列
- 11.4.4、改變列名
- 11.4.5、修改表名
- 11.5、洗掉表(DROP)
- 12、事務
- 12.1、模擬轉賬
- 12.1.1、 模擬賬戶轉錢
- 12.1.2 、模擬轉賬錯誤
- 12.2、事務的概念
- 12.3、事務的邊界
- 12.4、事務的原理
- 12.5、事務的特性
- 12.6、事務的應用
- 12.6.1 、事務完成轉賬
- 13、權限管理
- 13.1、創建用戶
- 13.2、授權
- 13.3、撤銷權限
- 13.4、洗掉用戶
- 14、視圖
- 14.1、視圖特點
- 14.2、視圖的創建
- 14.2.1 、創建視圖
- 14.2.2、使用視圖
- 14.3、視圖的修改
- 14.3.1、修改視圖_方式一
- 14.3.2、修改視圖_方式二
- 14.5、視圖的洗掉
- 14.5.1 洗掉視圖
- 14.6、視圖的注意事項
- 都看到這里了,有什么問題歡迎大佬在評論區批評指正!
1、寫在前面
我們在Java中存盤資料(變數、物件、陣列、集合),資料都是保存在記憶體中,屬于瞬時狀態資料;還有就是檔案存盤的方式,保存在硬碟上,屬于持久化狀態存盤;
雖然可以存盤但是都會有明顯的缺陷:
- 程式停止,資料就沒了,
- 檔案存盤的資料:沒有資料型別的區分
- 沒有訪問安全限制
- 沒有備份、恢復機制,
2、 資料庫的引入
2.1、資料庫是個啥?
資料庫是按照資料結構來組織、存盤、管理資料的倉庫,是一個可以長期存盤在計算機內的、有組織的、有共享的、可以統一管理的資料集合
2.2 資料庫的分類
- 網狀結構資料庫:以節點形式存盤資料和訪問資料
- 層次結構資料庫:IBM[IMS],定向有序的樹狀結構實作存盤和訪問,
- 關系結構資料庫:Oracle、MySQL、DB2、SQL Server,以表格(Table)形式存盤,多表之間建立關聯關系,通過分類、合并、連接、選取等方式實作訪問,
- 非關系型資料庫:MongDB、Redis,使用哈希表,表中以鍵值(key-value)的方式實作特定的鍵和一個指標指向的特定資料
- ElastecSearch
3、資料庫管理系統
資料庫管理系統指的是一種操作和管理資料庫的大型軟體,用于建立、使用、維護資料庫,對資料庫進行統一的管理和控制,保證資料庫的安全性和完整性,用戶可以通過資料庫管理系統訪問資料庫中的資料;
常見的資料庫管理系統
- Oracle:可以運行在UNIX、Windows等主流作業系統,支持所有的工業標準,并獲得了最高級別的ISO標準安全性認證,
- DB2:IBM公司的,滿足中大公司的需要
- SQL Server:微軟退出的,
- SQLLite:手機端的資料庫
- Mysql:免費、適合中小型企業
4、MySQL
MySQL是一個關系型資料庫管理系統,由瑞典MySQL AB公司開發的,屬于Oracle旗下的產品,是最流行的關系型資料庫管理系統之一,在WEB應用方面,是最好的應用軟體之一,
4.1、訪問與下載
官網:https://www.mysql.com
下載地址:https//dev.mysql.com/downloads/mysql/
4.2、安裝時的注意事項
- 不要有中文路徑,不要有特殊符號、空格
- 如果安裝中卡住了,一般超兩三分鐘,卸載(洗掉注冊表控制面板有一個卸載程式卸載, C盤目錄ProgramData隱藏檔案中洗掉Mysql內置的東西) ,重啟電腦在安裝;
- 如果沒有勾選自動配置環境變數,則需要手動添加
- 此電腦右擊選擇屬性之后點擊環境變數
- 創建MYSQL_HOME:C:\Program Files\MySQL\MySQL Server 5.7(MySQL安裝路徑)
- 追加Path:%MYSQL_HOME%\bin;
4.3、 MySQL的目錄結構
| 檔案夾名稱 | 內容 |
|---|---|
| bin | 命令相關檔案 |
| include | 庫檔案 |
| lib | 頭檔案 |
| Share | 字符集、語言等資訊 |
4.4、MySQL組態檔
在MySQL安裝目錄中找到my.ini的檔案,MySQL的一些配置引數
| 引數 | 描述 |
|---|---|
| default-character-set | 客戶端默認字符集 |
| character-set-server | 服務端默認字符集 |
| port | 客戶端和服務端的埠號 |
| default-storage-engine | MySQL的默認存盤引擎INNODB |
5、 SQL簡介
SQL是結構化查詢語言,用于存取資料、更新、查詢和管理關系資料庫系統的程式設計語言;
- 通常執行對資料庫的"增、刪、改 、查",簡稱C(Create)、R(Read)、U(Update)、D(Delete)
5.1、查看MySQL中所有資料庫
#連接到MySQL
SHOW DATABASES; #顯示當前MySQL中所有的資料庫
5.2、創建自定義資料庫
CREATE DATABASE
CREATE DATABASE dbtemp; #創建了名稱為dbtemp的資料庫
CREATE DATABASE dbtemp CHARACTER SET gbk;#創建資料庫并設定其默認字符集為GBK
CREATE DATABASE dbtemp CHARACTER SET GBK COLLATE gbk_chinese_ci;#支持簡體中文和繁體中文
CREATE DATABASE IF NOT EXISTS dbtemp;#如果dbtemp不存在,則創建,反之,不創建
5.3、洗掉資料庫
DROP DATABASE
DROP DATABASE dbtemp;#洗掉資料庫
5.4、查看資料庫創建資訊
SHOW CREATE DATABASE
SHOW CREATE DATABASE dbtemp;# 查看創建資料庫時的基本資訊
5.5、修改資料庫
ALTER DATABASE
ALTER DATABASE dbtemp CHARACTER SET UTF8;#修改資料庫dbtemp的字符集為utf-8
5.6、使用資料庫
USE
USE dbtemp;#當前環境下,操作dbtemp資料庫
5.7、查看當前使用的資料庫
SELECT DATABASE();
SELECT DATABASE();#查看當前使用的資料庫
6、客戶端工具
6.1 Navicat
Navicat是一套快速、可靠并且價格便宜的資料庫管理工具,專為簡化資料庫管理及降低系統管理成本而設,
6.2 SQLyog
SQLyog也擁有圖形化界面,擁有廣泛的預定義工具和查詢、友好的視覺界面,類似Excel的查詢結果編輯界面
6.3 DataGrip(Idea開發工具集成)
DataGrip是捷克公司的產品,需要付費,如果買了idea,DataGrip通用
7、 SQL語言分類
- 資料查詢語言DQL (Data Query Language):SELECT、WHERE、ORDER BY 、GROUP BY 、HAVING
- 資料定義語言DDL (Data Definition Language): CREATE、ALTER、DROP
- 資料操作語言DML(Data Manipulation Language):INSERT、UPDATE、DELETE
- 事務處理語言TPL (Transaction Process Language):COMMIT、ROLLBACK
- 資料控制語言DCL (Data Control Language):GRANT、REVOKE
8、 資料查詢
8.1 資料表的基本結構
關系結構資料庫是以表格(Table)進行資料存盤,表格由
行和列組成
- 執行查詢陳述句回傳的結果集是一張虛擬表
8.2、基本查詢
語法:SELECT 列名 FROM 表名
| 關鍵字 | 描述 |
|---|---|
| SELECT | 指定要查詢的列 |
| FROM | 指定要查詢的表 |
8.2.1、查詢所有列
#查詢t_employees表中所有員工的所有資訊
SELECT * FROM t_employees;
SELECT 所有的列名 FROM t_employees;
- 生產環境下,優先使用列名查詢,*的方式雖然看起來便捷,但實際上需要轉換成全列名,效率低,可讀性差
8.2.2 、查詢部分列
#查詢表中的所有員工的編號、姓氏、郵箱
SELECT EMPLOYEE_ID,FIRST_NAME,Email FROM t_employees;
#查詢表中所有員工的編號、部門編號
SELECT EMPLOYEE_ID,DEPARTMENT_ID FROM t_employees;
8.2.3 、對列中的資料進行運算
#查詢員工表中所有員工的編號、姓名、年薪
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY * 13 FROM t_employees;
| 算術運算子 | 描述 |
|---|---|
| + | 列與列之間做加法運算 |
| - | 列與列之間做減法運算 |
| * | 列與列之間做乘法運算 |
| / | 列與列之間做除法運算 |
- 注意: % 在資料庫中,代表的是占位符,而并非取余運算子
8.2.4 、列的別名
列 AS ‘列名’
#查詢員工表中所有員工的編號、姓名、日薪(列的運算 / 22),列名均為中文
SELECT EMPLOYEE_ID AS '編號',FIRST_NAME AS '姓',LAST_NAME AS '名',SALARY / 22 AS'日薪' FROM t_employees;
#起別名,沒有對原表的列名發生影響
8.2.5、 查詢結果去重
distinct 列名
#查詢員工表中,所有經理的ID編號
SELECT DISTINCT MANAGER_ID AS '經理編號' FROM t_employees;
#查詢員工表中,所有的工資 (去掉重復的)
SELECT DISTINCT SALARY FROM t_employees;
8.3 、排序查詢
語法: SELECT 列名 FROM 表名 ORDER BY 排序列名 [排序規則]
| 排序規則 | 描述 |
|---|---|
| ASC | 做升序排序 |
| DESC | 做降序排序 |
8.3.1、依據單列進行排序
#查詢員工的編號,名字,薪資,按照工資進行升序排序
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees ORDER BY salary ASC;
#查詢員工的編號,名字,薪資,按照姓名進行升序排序
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees ORDER BY FIRST_NAME ASC;
#查詢員工的編號,名字,薪資,按照工資進行降序排序
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees ORDER BY salary DESC;
- 當進行升序排序時,排序規則可以不顯示宣告,默認為升序排序規則
8.3.2 、依據多列進行排序
#查詢員工編號,名字,薪資,按照工資進行升序排序,如果工資相等,按照編號降序排序
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees
ORDER BY SALARY ASC,EMPLOYEE_ID DESC
#查詢員工編號,名字,薪資,按照工資進行升序排序,如果工資相等,按照姓名降序排序
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees
ORDER BY SALARY ASC,FIRST_NAME DESC
8.4 、條件查詢
語法: SELECT 列名 FROM 表名 WHERE 條件
| 關鍵字 | 描述 |
|---|---|
| WHERE | 在查詢結果中,篩選符合條件的查詢結果,條件為布爾運算式 |
8.4.1 、等值判斷(=)
#查詢工資為2500的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees WHERE salary = 2500;
#查詢姓為Steven的
SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM t_employees WHERE FIRST_NAME='Steven';
- 注意:與Java不同(==),MySQL中等值判斷用 =
8.4.2、不等值判斷(>、<、>=、<=、!=、<>)
#查詢員工工資大于6000的員工的資訊
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary>=6000;
#查詢員工工資不等于2500的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary<>2500;(!=同理)
8.4.3、邏輯判斷(and、or、not)
#查詢員工工資在6000~10000的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary>=6000 AND salary<=10000;
#查詢工資是10000的或者是9000的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary =10000 OR salary = 9000;
#查詢除了工資是10000的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE NOT salary =10000;
8.4.4 、區間判斷(between and)
#區間判斷 包含區間邊界的兩個值
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary BETWEEN 6000 AND 10000;
- 注意:between and要遵循 between 小值 and 大值;
8.4.5 、NULL值判斷(IS NULL、IS NOT NULL)
IS NULL
- 列名 IS NULL
IS NOT NULL
- 列名 IS NOT NULL
#查詢出 沒有經理編號的員工 IS NULL
SELECT EMPLOYEE_ID,FIRST_NAME,MANAGER_ID FROM t_employees
WHERE MANAGER_ID IS NULL;
#查詢出 沒有經理編號以外的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,MANAGER_ID FROM t_employees
WHERE MANAGER_ID IS NOT NULL;
#查詢出 沒有經理編號以外的員工資訊(此處NOT為取反,兩個結果)
SELECT EMPLOYEE_ID,FIRST_NAME,MANAGER_ID FROM t_employees
WHERE NOT MANAGER_ID IS NULL;
8.4.6 、列舉查詢(IN (值1,值2,值n…))
#列舉查詢 IN (值1,值2,值n...)
#查詢部門編號為70,80,90的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,DEPARTMENT_ID FROM t_employees
WHERE DEPARTMENT_ID IN(70,80,90);
#列舉查詢 查詢經理編號為 124 和100的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,MANAGER_ID FROM t_employees
WHERE MANAGER_ID IN(124,100);
8.4.7、 模糊查詢(_、%)
LIKE
- LIKE _(單個任意字符)
- 列名 LIKE ‘S_’
- LIKE %(任意長度的任意字符 0~n個)
- 列名 LIKE ‘S%’
#模糊查詢,查詢姓氏以S開頭且長度為6的員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME FROM t_employees
WHERE FIRST_NAME LIKE 'S_____';
#模糊查詢,查詢姓氏以S開頭任意長度的所有員工資訊
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME FROM t_employees
WHERE FIRST_NAME LIKE 'S%';
8.4.8 、分支結構查詢
CASE
WHEN 條件1 THEN 結果1
WHEN 條件2 THEN 結果2
WHEN 條件3 THEN 結果3
WHEN 條件4 THEN 結果4
ELSE 結果
END
- 通過使用CASE END進行條件判斷,每條資料對應生成一個值
- 類似Java中的分支結構
#查詢員工資訊(編號、名字、薪資、薪資級別<條件運算式>)
SELECT EMPLOYEE_ID,FIRST_NAME,salary,
CASE
WHEN salary >=10000 THEN 'A'
WHEN salary >=8000 AND salary<10000 THEN 'B'
WHEN salary >=6000 AND salary<8000 THEN 'C'
WHEN salary >=4000 AND salary <6000 THEN 'D'
ELSE 'E'
END AS '薪資級別'
FROM t_employees;
- 注意:case分支結構產生一個新的列
8.5、 時間查詢
語法: SELECT 時間函式([引數串列]);
- 執行時間函式查詢,會生成一張虛擬表(一行一列)
| 時間函式 | 描述 |
|---|---|
| SYSDATE() | 當前系統時間(年、月、日、時、分、秒) |
| CURDATE() | 獲得當前日期 |
| CURTIME() | 獲得當前時間 |
| WEEK(DATE) | 獲得指定日期是一年中第幾周 |
| YEAR(DATE) | 獲得指定日期的年份 |
| MONTH(DATE) | 獲得指定日期的月份 |
| DAY(DATE) | 獲得指定日期的天 |
| HOUR(DATE) | 獲得指定時間的小時值 |
| MINUTE(DATE) | 獲得指定時間的分鐘值 |
| SECOND(DATE) | 獲得指定日期的秒值 |
| DATEDIFF(DATE1,DATE2) | 獲得DATE1和DATE2之間相隔的天數 |
| ADDDATE(DATE,N) | 在指定日期加上N天后的日期 |
#1.當前系統時間
SELECT SYSDATE();
#2.獲得當前日期
SELECT CURDATE();
#3.獲得當前時間
SELECT CURTIME();
#4.獲得指定日期在一年中為第幾周
SELECT WEEK(CURDATE());
#5.獲取指定日期中的年份
SELECT YEAR(CURDATE());
#6.獲取指定日期中的月份
SELECT MONTH(CURDATE());
#7.獲取指定日期中的日
SELECT DAY(CURDATE());
#8.獲取指定日期中的時
SELECT HOUR(SYSDATE());
#9.獲取指定日期中的分
SELECT MINUTE(SYSDATE());
#10.獲取指定日期中的秒
SELECT SECOND(SYSDATE());
#11.獲取Date1和Date2之間相隔的天數
SELECT DATEDIFF(SYSDATE(),'2019-3-26');
#12.在指定日期之上加N天后的日期
SELECT ADDDATE(SYSDATE(),6);
8.6 、字串查詢
語法:SELECT 字串函式([引數串列]);
- 執行字串函式,產生一張虛擬表,(一行一列)
| 字串函式 | 說明 |
|---|---|
| CONCAT(str1,str2,str3…) | 將多個字串進行拼接 |
| INSERT(str,pos,len,newStr) | 將str中指定pos位置開始len長度的內容替換為newStr |
| LOWER(str) | 將指定字串轉換為小寫 |
| UPPER(str) | 將指定字串轉換為大寫 |
| SUBSTRING(str,pos,len) | 將str字串指定pos位置開始截取len個內容 |
#1.連接將多個字串連接在一起
SELECT CONCAT('My','S','QL');
#2.插入替換(下標從1開始)
SELECT INSERT('這是MySQL資料庫',3,5,'Oracle');
#3.轉小寫
SELECT LOWER('MYSQL');
#4.轉大寫
SELECT UPPER('mysql');
#5.截取
SELECT SUBSTRING('kak真的太帥了!我的天呀',3,4);
8.7、聚合函式
語法:SELECT 聚合函式(列名) FROM 表名;
- 聚合函式式對多條資料的單列進行統計,回傳統計后的一行結果
| 聚合函式 | 說明 |
|---|---|
| COUNT() | 求總行數 |
| SUM() | 求單列中所有行的總和 |
| AVG() | 求單列中所有行的平均值 |
| MAX() | 求單列中所有行的最大值 |
| MIN() | 求單列中所有行的最小值 |
8.7.1 、求總行數
#1.查詢員工一共多少人
SELECT COUNT(EMPLOYEE_ID) AS '員工總數' FROM t_employees;
SELECT COUNT(MANAGER_ID) AS '經理總數' FROM t_employees;
SELECT COUNT(*) FROM t_employees;
- 注意:聚合函式中,自動忽略null值,不進行統計
8.7.2、單列總和
#2.查詢員工每個月工資的總和
SELECT SUM(salary) FROM t_employees;
8.7.3、單列平均值
#3.查詢員工每個月工資的平均工資
SELECT AVG(salary) FROM t_employees;
8.7.4、單列最大值
#4.查詢月薪最高的
SELECT MAX(salary) FROM t_employees;
8.7.5 、單列最小值
#5.查詢月薪最低的
SELECT MIN(salary) FROM t_employees;
8.8、分組查詢
語法: SELECT 列名 FROM 表名 WHERE 條件 GROUP BY 分組依據(列名)
| 關鍵字 | 說明 |
|---|---|
| GROUP BY | 分組依據,如果有WHERE,在WHERE之后生效 |
8.8.1、查詢各部門的總人數
#思路:
#1.先按照部門編號分組(分組依據是:department_id)
#2.再針對各部門的人數進行統計(count)
SELECT DEPARTMENT_ID,COUNT(EMPLOYEE_ID)
FROM t_employees
GROUP BY DEPARTMENT_ID;
8.8.2、查詢各部門的平均工資
#思路:
#1.先按照部門編號分組(分組依據是:department_id)
#2.再針對各部門的工資進行平均計算(AVG())
SELECT DEPARTMENT_ID,AVG(salary) AS '平均工資',COUNT(EMPLOYEE_ID) AS'人數'
FROM t_employees
GROUP BY DEPARTMENT_ID;
8.8.3、查詢各個部門、各個崗位的人數
#思路
#1.按照部門編號進行分組(department_id)
#2.按照崗位名稱進行分組(job_id)
#3.針對每個部門中各個崗位的人數進行統計
SELECT DEPARTMENT_ID AS'部門',JOB_ID AS'崗位',COUNT(EMPLOYEE_ID) AS'人數'
FROM t_employees
GROUP BY DEPARTMENT_ID,JOB_ID;
8.8.4、常見問題
#查詢各個部門的id、總人數、first_name
SELECT DEPARTMENT_ID,COUNT(EMPLOYEE_ID),FIRST_NAME
FROM t_employees
GROUP BY DEPARTMENT_ID;
- 注意:分組查詢中,select顯示的列只能是分組依據的列或者是聚合函式列,不能出現其他列,
8.9 、分組過濾查詢
語法: SELECT 列名 FROM 表名 WHERE 條件 GROUP BY 分組依據(列名) HAVING 過濾規則
| 關鍵字 | 說明 |
|---|---|
| HAVING | 過濾規則是對分組后的資料進行過濾 |
8.9.1、 統計部門中的最高工資
#統計部門編號為60、70、80的部門最高工資
#思路:
#1.確定分組依據 department_id
#2.對分組后的資料進行過濾 過濾規則為 60 70 80部門編號
#3.分組過濾后的資料,做max()函式處理
SELECT DEPARTMENT_ID,MAX(salary)
FROM t_employees
GROUP BY DEPARTMENT_ID
HAVING DEPARTMENT_ID IN (60,70,80);
#HAVING是在分組之后的資料進行過濾
8.10、限定查詢
語法:SELECT 列名 FROM 表名 LIMIT 起始行,查詢行
| 關鍵字 | 描述 |
|---|---|
| LIMIT offset_start,row_count | 限定查詢結果的起始行和總行數 |
8.10.1、查詢前5行記錄
#查詢表中前五名員工的資訊
SELECT * FROM t_employees LIMIT 0,5;
- 注意:起始行是從0開始,代表了第一行,第二個引數代表的是從指定行開始查詢幾行
8.10.2 、查詢范圍記錄
#查詢表中的第二頁資料和第三頁資料
SELECT * FROM t_employees LIMIT 5,5;
SELECT * FROM t_employees LIMIT 10,5;
- 在分頁的應用場景中,起始行是跟隨頁數變化的,但是一頁顯示的條數是不變得
8.11、查詢總結
8.11.1 、SQL陳述句撰寫順序
SELECT 列名 FROM 表名 WHERE 條件 GROUP BY 分組 HAVING 過濾條件 ORDER BY 排序列 LIMIT 起始行,總條數
8.11.2、SQL陳述句執行順序
- 執行 FROM : 指定資料來源表
- 執行WHERE : 對查詢的資料做第一次過濾
- 執行GROUP BY :分組
- 執行HAVING : 對分組后的資料做第二次過濾
- 執行SELECT : 查詢各個欄位的值
- 執行ORDER BY : 排序
- 執行LIMIT : 限定查詢結果
8.12、子查詢(作為條件判斷)
語法:SELECT 列名 FROM 表名 WHERE 條件(子查詢結果)
8.12.1、查詢工資大于Bruce的員工資訊
#思路
#1.先查詢到Bruce的工資(一行一列)
SELECT SALARY FROM t_employees WHERE first_name = 'Bruce';#6000
#2.查詢大于Bruce工資的員工資訊
SELECT * FROM t_employees WHERE SALARY > 6000;
#3.將1 、2 整合為一條陳述句
SELECT * FROM t_employees WHERE salary >(SELECT SALARY FROM t_employees WHERE first_name = 'Bruce');
- 注意:將子查詢"一行一列"的結果作為外部查詢的條件,做第二次查詢
- 子查詢得到的是一行一列的結果才能作為外部條件的等值或不等值判斷條件
8.13、子查詢(作為列舉查詢的條件)
語法:SELECT 列名 FROM 表名 WHERE 列名 IN(子查詢結果)
8.13.1、查詢與King同一部門員工資訊
#思路
#1.查詢King所在的部門編號(多行單列)
SELECT DEPARTMENT_ID FROM t_employees WHERE last_name='King';
#2.將 80、90作為列舉查詢的條件
SELECT EMPLOYEE_ID,FIRST_NAME,salary
FROM t_employees
WHERE DEPARTMENT_ID IN (80,90)
#3.整合
SELECT EMPLOYEE_ID,FIRST_NAME,salary
FROM t_employees
WHERE DEPARTMENT_ID
IN
(SELECT DEPARTMENT_ID FROM t_employees WHERE last_name='King')
- 將子查詢得到的"多行一列"的結果作為外部查詢的列舉查詢條件,做第二次查詢
8.13.2、工資高于部門編號為60的所有人的資訊
#1.查詢部門編號為60的工資
SELECT salary FROM t_employees WHERE DEPARTMENT_ID = 60;
#2.查詢高于60部門所有人的工資的員工資訊(高于所有人!)
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary > ALL
(SELECT salary FROM t_employees WHERE DEPARTMENT_ID = 60);
#3.查詢高于60部門所有人的工資的員工資訊(高于部分人!)
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees
WHERE salary > ANY
(SELECT salary FROM t_employees WHERE DEPARTMENT_ID = 60);
- 注意:當子查詢結果集為多行單列時,也可以使用ALL匹配所有或者ANY匹配部分
8.14、子查詢(作為一張表)
語法:SELECT 列名 FROM (子查詢結果集) WHERE 條件;
8.14.1 、查詢表中部分列的資訊,獲得工資大于15000的
#思路
#1.先查詢部分列的資訊作為一張臨時表
SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees;
#2.將子查詢得到的臨時表作為外部查詢的表
SELECT EMPLOYEE_ID ,FIRST_NAME ,salary
FROM
(SELECT EMPLOYEE_ID,FIRST_NAME,salary FROM t_employees)AS temp
WHERE salary > 15000;
- 經驗:將子查詢得到的"多行多列"的結果作為外部查詢的一張臨時表,做第二次查詢
8.15、合并查詢
語法:
- SELECT 列名 FROM 表名 1 UNION SELECT 列名 FROM 表名2
- SELECT 列名 FROM 表名 1 UNION ALL SELECT 列名 FROM 表名2
8.15.1、合并兩張表的結果(去除重復記錄)
#合并 t1 和t2兩張表的結果,縱向合并,去除重復的記錄
SELECT * FROM t1
UNION
SELECT * FROM t2
8.15.2 、合并兩張表的結果(保留重復記錄)
#合并結果集,不去除重復記錄
SELECT * FROM t1
UNION ALL
SELECT * FROM t2
- 注意:合并的兩個結果集,列數必須相同,列型別、列名可以不同
8.16、表連接查詢
語法:SELECT 列名 FROM 表1 連接方式 表2 ON 連接條件;
8.16.1、內連接查詢(INNER JOIN ON)
#查詢所有有部門的員工資訊,顯示部門名稱(不包括沒有部門的員工) SQL標準
SELECT * FROM t_employees
INNER JOIN t_departments
ON t_employees.`DEPARTMENT_ID` = t_departments.`DEPARTMENT_ID`;
#MYSQL標準
SELECT EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME FROM
t_employees,t_departments
WHERE t_employees.`DEPARTMENT_ID` = t_departments.`DEPARTMENT_ID`;
#1.兩張表連接查詢,要有關聯條件,但是關聯條件的列重復了,需要明確查詢的是哪個表的列
#2.表名比較長,表名多次重復出現,容易混淆.可以給別名
SELECT EMPLOYEE_ID,FIRST_NAME,d.DEPARTMENT_ID,DEPARTMENT_NAME FROM t_employees AS e
INNER JOIN t_departments AS d
ON e.`DEPARTMENT_ID` = d.`DEPARTMENT_ID`;
- 在MySQL中,可以使用第二種方式,不符合SQL標準
- 第一種,屬于SQL標準,與其他關系型資料庫通用
8.16.2 、內連接查詢
#查詢所有崗位的員工資訊,顯示崗位名稱
SELECT EMPLOYEE_ID,FIRST_NAME,JOB_TITLE
FROM t_employees AS e
INNER JOIN t_jobs AS j
ON e.`JOB_ID` = j.`JOB_ID`;
8.16.3、三表連接查詢
#查詢所有員工工號、名字、部門名稱、部門所在城市的名稱
SELECT EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME,CITY
FROM t_employees AS e
INNER JOIN t_departments AS d
ON e.`DEPARTMENT_ID` = d.`DEPARTMENT_ID`
INNER JOIN t_locations AS l
ON d.`LOCATION_ID` = l.`LOCATION_ID`;
8.16.4、多表連接查詢
#查詢所有員工工號、名字、部門名稱、部門城市名稱、所在城市的國家
SELECT EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME,CITY,COUNTRY_NAME
FROM t_employees AS e
INNER JOIN t_departments AS d
ON e.`DEPARTMENT_ID` = d.`DEPARTMENT_ID`
INNER JOIN t_locations AS l
ON d.`LOCATION_ID` = l.`LOCATION_ID`
INNER JOIN t_countries AS c
ON l.`COUNTRY_ID` = c.`COUNTRY_ID`;
- 經驗:多表查詢時,要明確哪一張表和連接的表有關系,
8.16.5、左外連接查詢(LEFT JOIN ON)
#查詢所有員工資訊,以及對應的部門名稱(沒有部門的員工,也在查詢結果中,但是部門名稱以NULL填充)
SELECT EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME
FROM t_employees AS e
LEFT JOIN t_departments AS d
ON e.`DEPARTMENT_ID` = d.`DEPARTMENT_ID`;
- 注意:左外連接,是以左表為主表,依次向右表匹配,匹配到,則回傳正確結果
- 匹配不到,則回傳NULL值,填充顯示
8.16.6、右外連接查詢(RIGHT JOIN ON)
#查詢所有部門資訊,以及部門中的員工資訊
#(沒有員工的部門,也在查詢結果中,員工資訊以NULL填充)
SELECT EMPLOYEE_ID,FIRST_NAME,DEPARTMENT_NAME
FROM t_employees AS e
RIGHT JOIN t_departments AS d
ON e.`DEPARTMENT_ID` = d.`DEPARTMENT_ID`;
- 注意:右外連接,是以右表為主表,依次向左匹配,匹配到,回傳正確結果
- 匹配不到,則回傳NULL填充
9、 DML操作(增、刪、改)
9.1、新增(INSERT)
INSERT INTO 表名 (列1,列2,列3…) VALUES(值1,值2,值3…)
#添加一條員工資訊
INSERT INTO t_employees
(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,COMMISSION_PCT,MANAGER_ID,DEPARTMENT_ID)
VALUES('209','Ya','Suo','123@happy.com','515.123.6666','2010-03-18','Center',900,NULL,'123','50')
#多行添加,在值串列外邊追加,再寫一個值串列
,('208','Ya','Suo','YaSuo@happy.com','515.123.6666','2010-03-18','Center',900,NULL,'123','50');
#添加一條城市資訊
INSERT INTO t_countries(COUNTRY_ID,COUNTRY_NAME)VALUES('AL','阿爾巴尼亞');
SELECT * FROM t_departments;
#添加一條部門資訊
INSERT INTO t_departments(DEPARTMENT_ID,DEPARTMENT_NAME,MANAGER_ID,LOCATION_ID)
VALUES('280','Teach','111','1500')
- 注意:表名后的列名串列以及VALUES里的值串列要一一對應(個數、順序、型別)
9.2、修改(UPDATE)
UPDATE 表名 SET 列名1=新值1,列名2 = 新值2… WHERE 條件
#修改員工編號為208的員工名字為TOM Jackson
UPDATE t_employees SET FIRST_NAME='TOM', LAST_NAME = 'Jackson' WHERE EMPLOYEE_ID = '208';
- 注意:SET后跟著多個列 = 值,絕大多數情況下,都要加WHERE條件,指定修改的目標,否則為整表更新
9.3、洗掉
DELETE FROM 表名 WHERE 條件
#洗掉一條員工,編號為207的
DELETE FROM t_employees WHERE EMPLOYEE_ID = '207'
- 注意:洗掉時,如若不加WHERE條件,洗掉的是整張表的資料,結構不變
9.4、清空(TRUNCATE)
清空整張表:TRUNCATE TABLE 表名;
#清空t2整張表
TRUNCATE TABLE t2;
注意:TRUNCATE與DELETE不加WHERE,洗掉整張表資料不同:
- DELETE僅僅洗掉資料,結構不變
- TRUNCATE是把整張表銷毀,再按照原表的格式、結構創建一張新表
10、庫表操作
10.1、資料庫創建(CREATE)
CREATE DATABASE 庫名
#創建默認字符集的資料庫
CREATE DATABASE MYDB1;
#創建指定字符集的資料庫
CREATE DATABASE MYDB1 CHARACTER SET UTF8;
10.2、修改資料庫
ALTER DATABASE 庫名 操作
10.2.1、修改資料庫的字符集
#修改mydb1的字符集給gbk
ALTER DATABASE MYDB1 CHARACTER SET GBK;
10.3 洗掉資料庫
洗掉資料庫:DROP DATABASE 庫名
#洗掉mydb1資料庫
DROP DATABASE MYDB1;
10.4、資料型別
MySQL大致可以分為三類:數值、日期/時間、字串(字符)型別,對于我們建表,約束列的型別有很大的幫助;
10.4.1 、數值型別
| 型別 | 大小 | 范圍(有符號) | 范圍(無符號) | 用途 |
|---|---|---|---|---|
| INT | 4位元組 | (-2147483648,2147483647) | (0,4294967295) | 整數值 |
| DOUBLE | 8位元組 | (-1.797E+308,-2.22E-308) | (0,2.22E-308,1.797E+308) | 雙精度浮點值 |
| DOUBLE(M,D) | 8位元組,M表示長度,D表示小數位數 | 同上,受M和D的約束,DOUBLE(5,2)-999.99-999.99 | 同上,受M和D的約束 | 雙精度浮點值 |
| DECIMAL(M,D) | 保存精確值 | 依賴M和D, | 依賴M和D | 小數值 |
10.4.2 、日期型別
| 型別 | 大小 | 范圍 | 格式 | 用途 |
|---|---|---|---|---|
| DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
| TIME | 3 | ‘-838:59:59’/‘838:59:59’ | HH:MM:SS | 時間值 |
| YEAR | 1 | 1901/2155 | YYYY | 年分值 |
| DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM–DD HH:MM:SS | 混合日期時間值 |
10.4.3、字串型別
| 型別 | 大小 | 用途 |
|---|---|---|
| CHAR | 0-255字符 | 定長字串 CHAR(10) 10個字符 |
| VARCHAR | 0-65535 | 可變長字串 VARCHAR(10) 10個字符 |
| BLOB(binary large object) | 0-65535 | 二進制形式的長文本資料 |
| TEXT | 0-65535 | 長文本 |
10.5、資料表的創建(CREATE)
CREATE TABLE 表名(
? 列名 資料型別 [約束],
? 列名 資料型別 [約束],
? …
? 列名 資料型別 [約束] //最后一列的創建,末尾不需要加逗號
)[charset=utf8]; //根據需要指定表的字符編碼集
#創建科目表
#科目編號、科目名稱、科目學時
#Subject
CREATE TABLE `Subject`(
subjectId INT,
subjectName VARCHAR(20),
subjectHours INT
)CHARSET=utf8;
INSERT INTO `subject`(subjectid,subjectname,subjecthours)
VALUES(1,'Java',10);
INSERT INTO `subject`(subjectid,subjectname,subjecthours)
VALUES(2,'HTML5',20);
INSERT INTO `subject`(subjectid,subjectname,subjecthours)
VALUES(3,'BIGDATA',5);
11、約束
11.1、物體完整性約束
表中一行資料代表一個物體(entity),物體完整性約束是標識每一行資料不重復、物體唯一,
11.1.1 、主鍵約束
PRIMARY KEY 唯一,標識表中的一行資料,此列的值不可重復,且不能為NULL
#創建表中,選擇適合做主鍵的列,添加主鍵約束
CREATE TABLE Student(
stuid INT PRIMARY KEY,#標識每一個學生的編號是唯一的,不能為NULL
stuName VARCHAR(20),
phone VARCHAR(11)
)CHARSET=utf8;
11.1.2、唯一約束
UNIQUE 唯一,標識表中的一行資料,不可重復,可以為NULL
#表中的手機號列,添加唯一約束!不能重復,但是可以為NULL
CREATE TABLE Student(
stuid INT PRIMARY KEY,#標識每一個學生的編號是唯一的,不能為NULL
stuName VARCHAR(20),
phone VARCHAR(11) UNIQUE
)CHARSET=utf8;
11.1.3、自動增長列
AUTO_INCREMENT 自動增長,給主鍵數值列添加自動增長,從1開始,每次加1,不能單獨使用,和主鍵搭配
#為表中的主鍵列添加自動增長,避免ID重復,也容易忘記
CREATE TABLE Student(
stuid INT PRIMARY KEY AUTO_INCREMENT,#會從1開始,根據添加資料的順序依次+1
stuName VARCHAR(20),
phone VARCHAR(11) UNIQUE
)CHARSET=utf8;
11.2、域完整性約束
限制列的每一個單元格的資料正確性
11.2.1、非空約束
NOT NULL 非空,約束此列的每一個單元格不允許有NULL
#加了NOT NULL的約束列,必須有值
CREATE TABLE emp(
id INT PRIMARY KEY AUTO_INCREMENT,
empName VARCHAR(20)NOT NULL,#約束名字這一列必須有值
address VARCHAR(50) NOT NULL
)CHARSET=utf8;
INSERT INTO emp(empName,address) VALUES(null,'北京市海淀區');#error,課程名稱必須有值
11.2.2、默認值約束
DEFAULT 為列賦予默認值,當新增的資料不指定值時,可以書寫DEFAULT,以定義好的默認值進行填充
#默認值約束,如果沒有指定值,填充DEFAULT,默認值,
CREATE TABLE emp(
id INT PRIMARY KEY AUTO_INCREMENT,
empName VARCHAR(20)NOT NULL,#約束名字這一列必須有值
address VARCHAR(50) NOT NULL,
sex CHAR(1) DEFAULT '女'
)CHARSET=utf8;
11.2.3 、參考完整性約束
語法:CONSTRAINT 參考名 FOREIGN KEY (列名) REFERENCES 被參考表名(列名)
- FOREIGN KEY 參考外部表的某5個列的值,新增資料時,約束此列的值必須是被參考表中存在的值
#專業表
CREATE TABLE Speciality(
id INT PRIMARY KEY AUTO_INCREMENT,
SpecialName VARCHAR(20) UNIQUE NOT NULL#唯一,且不能為空
)CHARSET=utf8;
#課程表
CREATE TABLE `subject`(
subjectid INT PRIMARY KEY AUTO_INCREMENT,
subjecname VARCHAR(20) UNIQUE NOT NULL,
subjecthours INT DEFAULT 20,
specialid INT NOT NULL,
CONSTRAINT fk_subject_specialid
FOREIGN KEY(specialid)
REFERENCES Speciality(id)
)CHARSET=utf8;
SELECT * FROM SUBJECT;
#存在參考關系的表,要先添加被參考的表資料(主鍵表).再添加參考表的資料(外鍵表)
INSERT INTO Speciality (SpecialName) VALUES('Java');
INSERT INTO Speciality (SpecialName) VALUES('HTML5');
INSERT INTO `subject`(subjecname,subjecthours,specialid)
VALUES('JavaSE',10,1);
INSERT INTO `subject`(subjecname,subjecthours,specialid)
VALUES('JavaScript',20,2);
INSERT INTO `subject`(subjecname,subjecthours,specialid)
VALUES('BIGDATA',20,3);#error 約束:主鍵表不存在3.所以外鍵表不能插入3
- 注意:兩張表存在參考關系時,執行洗掉操作需要注意,先洗掉從表(參考表、外鍵表),再洗掉主表(被參考表、主鍵表)
11.3、約束創建整合
創建帶有約束的表
11.3.1 、創建Grade表
| 列名 | 資料型別 | 約束 | 說明 |
|---|---|---|---|
| GradeId | INT | 主鍵、自動增長 | 班級編號 |
| GradeName | VARCHAR(20) | 唯一、非空 | 班級名稱 |
#創建Grade表
CREATE TABLE Grade(
GradeId INT PRIMARY KEY AUTO_INCREMENT,
GradeName VARCHAR(20) UNIQUE NOT NULL
)CHARSET=utf8;
SELECT * FROM grade;
INSERT INTO Grade(GradeName) VALUES('001');
INSERT INTO Grade(GradeName) VALUES('002');
INSERT INTO Grade(GradeName) VALUES('003');
11.3.2、創建Student表
| 列名 | 資料型別 | 約束 | 說明 |
|---|---|---|---|
| student_id | VARCHAR(50) | 主鍵 | 學號 |
| student_name | VARCHAR(50) | 非空 | 姓名 |
| sex | CHAR(2) | 默認值,男 | 性別 |
| borndate | DATE | 非空 | 生日 |
| phone | VARCHAR(11) | 無 | 電話 |
| GradeId | INT | 非空,外鍵約束:參考班級表的GradeId | 班級編號 |
#創建Student表
CREATE TABLE Student(
student_id VARCHAR(50) PRIMARY KEY,
student_name VARCHAR(50) NOT NULL,
sex CHAR(2) DEFAULT '男',
borndate DATE NOT NULL,
phone VARCHAR(11),
GradeId INT NOT NULL,
CONSTRAINT fk_student_gradeId FOREIGN KEY(GradeId) REFERENCES Grade(GradeId)
)CHARSET=utf8;
SELECT * FROM student;
INSERT INTO student(student_id,student_name,sex,borndate,phone,GradeId)
VALUES('S1001','kak1',DEFAULT,'2001-06-01',NULL,2);
INSERT INTO student(student_id,student_name,sex,borndate,phone,GradeId)
VALUES('S1002','kak2',DEFAULT,'1999-06-01',NULL,3);
- 注意:在創建有關系關聯表時,要先創建主表(主鍵),再創建從表(外鍵表)
11.4、資料表的修改(ALTER)
語法:ALTER TABLE 表名 修改操作;
11.4.1、向現有表中添加列
#向現有表中添加列
ALTER TABLE Student ADD image BLOB;
#ADD 新列名 資料型別 [約束]
11.4.2 、修改表中的列
ALTER TABLE student MODIFY phone VARCHAR(14) NOT NULL
- 注意:修改表中的某列時,需要寫全列的名字、資料型別、約束
11.4.3、洗掉表中的列
ALTER TABLE student DROP image;
11.4.4、改變列名
ALTER TABLE student CHANGE borndate birthday DATE NOT NULL;
- 注意:改變列名時,在給定新列名的同時,要指定列的資料型別和約束
11.4.5、修改表名
ALTER TABLE student RENAME stu;
11.5、洗掉表(DROP)
洗掉學生表:DROP TABLE 表名
DROP TABLE stu
12、事務
12.1、模擬轉賬
生活中轉賬是轉賬方扣錢,收錢方賬戶價錢,用資料庫操作來模擬現實轉賬,
12.1.1、 模擬賬戶轉錢
#1賬號轉錢給2賬戶1000元
#1賬戶扣錢
UPDATE account SET money = money - 1000 WHERE id = 1;
#2賬戶加錢
UPDATE account SET money = money + 1000 WHERE id = 2;
12.1.2 、模擬轉賬錯誤
#1賬號轉錢給2賬戶1000元
#1賬戶扣錢
UPDATE account SET money = money - 1000 WHERE id = 1;
#斷電、例外、出錯
#2賬戶加錢
UPDATE account SET money = money + 1000 WHERE id = 2;
- 上述代碼在減錢操作程序中出現了例外或陳述句出錯,會發現,減錢仍舊成功,而加錢失敗了
- 每條SQL陳述句都是一個獨立的操作!任何一個操作執行完對資料庫是永久性的影響
12.2、事務的概念
事務是一個原子操作,是一個最小執行單元,可以由一個或多個SQL陳述句組成,在同一個事務中,所有的SQL陳述句都成功執行時,整個事務成功!有一個SQL陳述句執行失敗,整個事務都執行失敗!
12.3、事務的邊界
開始:連接到資料庫,執行一條DML陳述句, 上一個事務結束后,又輸入了一條DML陳述句,即事務的開始
結束:
- 提交:
- 顯示提交:COMMIT;
- 隱式提交:一條DML陳述句,正常退出(客戶端退出鏈接)
- 回滾:
- 顯示回滾:ROLLBACK;
- 隱式回滾:非正常退出(斷電、死機),執行了創建、洗掉的陳述句,但是失敗了!會為這個無效的SQL陳述句執行回滾,
12.4、事務的原理
資料庫會為每一個客戶端都維護一個空間獨立的快取區(回滾段),一個事務中所有的增刪改陳述句的執行結果都會快取在回滾段中,只有當事務中所有的SQL陳述句均正常結束(COMMIT),才會將回滾段中的資料同步到資料庫,否則無論因為任何原因失敗了,則整個事務回滾(ROLLBACK);
12.5、事務的特性
Atomicity(原子性):表示的是一個事務內的所有操作是一個整體,要么全部成功,要么全部失敗,
Consistency(一致性):表示一個事務內有一個操作失敗時,所有的更改過得資料都必須回滾到修改前狀態,
Isolation(隔離性):事務查看資料操作時資料所處的狀態,要么是另一個并發事務修改資料之前的狀態,要么是另一個并發事務修改它之后的狀態,事務不會查看中間狀態的資料
Durability(持久性):事務完成之后,對于資料庫的影響是永久性的,
12.6、事務的應用
應用環境:基于增刪改陳述句的操作結果(均回傳操作后受影響的行數),可通程序式邏輯手動控制事務的提交或回滾
12.6.1 、事務完成轉賬
#開啟事務
START TRANSACTION;#SET autoCommit = 0;#方式2 設定自動提交為0 關閉自動提交 | 1 開啟自動提交
#1賬戶扣錢
UPDATE account SET money = money - 1000 WHERE id = 1;
#2賬戶加錢
UPDATE account SET money = money + 1000 WHERE id = 2;
#執行提交 ---成功
COMMIT;
#執行回滾 ---失敗
ROLLBACK;
- 注意:開啟事務后,在當前事務內執行的陳述句均屬于當前事務,成功再執行COMMIT,失敗要進行ROLLBACK
13、權限管理
13.1、創建用戶
創建一個用戶:CREATE USER 用戶名 IDENTIFIED BY 密碼
#創建用戶
CREATE USER 'kak' IDENTIFIED BY '123';
13.2、授權
用戶授權:GRANT ALL ON 資料庫.表名 TO 用戶名;
#將companydb資料里的grade表授權給zhangsan
GRANT ALL ON companydb.`grade` TO 'kak';
#將companydb資料庫里的所有表授權給zhangsan
GRANT ALL ON companydb.* TO 'kak';
13.3、撤銷權限
撤銷用戶權限:REVOKE ALL ON 資料庫.表名 FROM 用戶名
REVOKE ALL ON companydb.grade FROM 'kak';
13.4、洗掉用戶
洗掉用戶:DROP USER 用戶名;
DROP USER 'kak';
14、視圖
視圖又叫虛擬表,從一個表中或多個表中查詢出來的結果表,作用和真實表一樣,包含一系列的帶有行和列的資料,視圖中,可以使用SELECT陳述句查詢資料,也可以使用INSERT、UPDATE、DELETE修改記錄,視圖可以使用戶操作方便,并保障了資料庫系統安全;
14.1、視圖特點
優點
- 簡單化,資料所見即所得
- 安全性,只能查詢或修改視圖中鎖能見到的資料
- 邏輯獨立性,可以屏蔽真實表結構變化帶來的影響,
缺點
- 性能相對較差,簡單的查詢會稍微復雜
- 修改不方便,當視圖的資料時復雜的聚合視圖時,無法修改,
14.2、視圖的創建
語法:CREATE VIEW 視圖名 AS 查詢資料源表的陳述句;
14.2.1 、創建視圖
#創建一個t_empinfo視圖,該視圖的資料是員工姓名,郵箱,手機號碼
CREATE VIEW t_empinfo
AS
SELECT FIRST_NAME,LAST_NAME,email,PHONE_NUMBER FROM t_employees;
14.2.2、使用視圖
#使用視圖
#查詢,所見即所得
SELECT * FROM t_empinfo WHERE FIRST_NAME='Steven' AND LAST_NAME='King';
#修改,只能修改得到的
UPDATE t_empinfo SET email = 'Kings' WHERE FIRST_NAME='Steven' AND LAST_NAME='King';
14.3、視圖的修改
14.3.1、修改視圖_方式一
存在就替換資料,不存在就新建:CREATE OR REPLACE VIEW 視圖名 AS 查詢源表的陳述句;
CREATE OR REPLACE VIEW t_empinfo AS
SELECT employee_id,FIRST_NAME,LAST_NAME,email,PHONE_NUMBER FROM t_employees;
14.3.2、修改視圖_方式二
ALTER VIEW 視圖名 AS查詢源表的陳述句;
ALTER VIEW t_empinfo AS
SELECT FIRST_NAME,LAST_NAME,email,PHONE_NUMBER FROM t_employees;
14.5、視圖的洗掉
DROP VIEW 視圖名
14.5.1 洗掉視圖
DROP VIEW t_empinfo;
- 注意:洗掉視圖不會影響原表的資料
14.6、視圖的注意事項
視圖不會獨立存盤資料,原表發生改變,視圖的資料也發生改變,沒有優化查詢的性能
如果視圖包含以下結構中的一種,則視圖不可更新:
- 聚合函式的結果
- GROUP BY分組后的結果
- HAVING篩選過濾后的結果
- UNION、UNION ALL聯合后的結果
都看到這里了,有什么問題歡迎大佬在評論區批評指正!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/390392.html
標籤:其他
