MYSQL数据库详解-从零入门,一篇正式入门
MYSQL
- 1,數據庫相關概念
- 1.1 數據庫
- 1.2 數據庫管理系統
- 1.3 常見的數據庫管理系統
- 1.4 SQL
- 2,MySQL
- 2.1 MySQL安裝
- 2.1.1 下載
- 2.1.2 安裝(解壓)
- 2.2 MySQL卸載
- 2.3 MySQL配置
- 2.3.1 添加環境變量
- 2.3.2 新建配置文件
- 2.3.3 初始化MySQL
- 2.3.4 注冊MySQL服務
- 2.3.5 啟動MySQL服務
- 2.3.6 修改默認賬戶密碼
- 2.4 MySQL登陸和退出
- 2.4.1 登陸
- 2.4.2 退出
- 2.5 MySQL數據模型
- 3,SQL概述
- 3.1 SQL簡介
- 3.2 通用語法
- 3.3 SQL分類
- 4,DDL:操作數據庫
- 4.1 查詢
- 4.2 創建數據庫
- 4.3 刪除數據庫
- 4.4 使用數據庫
- 5,DDL:操作表
- 5.1 查詢表
- 5.2 創建表
- 5.3 數據類型
- 5.4 刪除表
- 5.5 修改表
- 6,navicat使用
- 6.1 navicat概述
- 6.2 navicat安裝
- 6.3 navicat使用
- 6.3.1 建立和mysql服務的連接
- 6.3.2 操作
- 7,DML
- 7.1 添加數據
- 7.2 修改數據
- 7.3 刪除數據
- 8,DQL
- 8.1 基礎查詢
- 8.1.1 語法
- 8.1.2 練習
- 8.2 條件查詢
- 8.2.1 語法
- 8.2.2 條件查詢練習
- 8.2.3 模糊查詢練習
- 8.3 排序查詢
- 8.3.1 語法
- 8.3.2 練習
- 8.4 聚合函數
- 8.4.1 概念
- 8.4.2 聚合函數分類
- 8.4.3 聚合函數語法
- 8.4.4 練習
- 8.5 分組查詢
- 8.5.1 語法
- 8.5.2 練習
- 8.6 分頁查詢
- 8.6.1 語法
- 8.6.2 練習
- 9,約束
- 9.1 概念
- 9.2 分類
- 9.3 非空約束
- 9.4 唯一約束
- 9.5 主鍵約束
- 9.6 默認約束
- 9.7 約束練習
- 9.8 外鍵約束
- 9.8.1 概述
- 9.8.2 語法
- 9.8.3 練習
- 10,數據庫設計
- 10.1 數據庫設計簡介
- 10.2 表關系(一對多)
- 10.3 表關系(多對多)
- 10.4 表關系(一對一)
- 10.5 數據庫設計案例
- 11,多表查詢
- 11.1 內連接查詢
- 11.2 外連接查詢
- 11.3 子查詢
- 11.4 案例
- 12,事務
- 12.1 概述
- 12.2 語法
- 12.3 代碼驗證
- 12.4 事務的四大特征
1,數據庫相關概念
1.1 數據庫
-
存儲和管理數據的倉庫,數據是有組織的進行存儲。
-
數據庫英文名是 DataBase,簡稱DB。
數據庫就是將數據存儲在硬盤上,可以達到持久化存儲的效果。
1.2 數據庫管理系統
- 管理數據庫的大型軟件
- 英文:DataBase Management System,簡稱 DBMS
在電腦上安裝了數據庫管理系統后,就可以通過數據庫管理系統創建數據庫來存儲數據,也可以通過該系統對數據庫中的數據進行數據的增刪改查相關的操作。我們平時說的MySQL數據庫其實是MySQL數據庫管理系統。
通過上面的描述,大家應該已經知道了 數據庫管理系統 和 數據庫 的關系。那么有有哪些常見的數據庫管理系統呢?
1.3 常見的數據庫管理系統
接下來對上面列舉的數據庫管理系統進行簡單的介紹:
- Oracle:收費的大型數據庫,Oracle 公司的產品
- MySQL: 開源免費的中小型數據庫。后來 Sun公司收購了 MySQL,而 Sun 公司又被 Oracle 收購
- SQL Server:MicroSoft 公司收費的中型的數據庫。C#、.net 等語言常使用
- PostgreSQL:開源免費中小型的數據庫
- DB2:IBM 公司的大型收費數據庫產品
- SQLite:嵌入式的微型數據庫。如:作為 Android 內置數據庫
- MariaDB:開源免費中小型的數據庫
1.4 SQL
- 英文:Structured Query Language,簡稱 SQL,結構化查詢語言
- 操作關系型數據庫的編程語言
- 定義操作所有關系型數據庫的統一標準,可以使用SQL操作所有的關系型數據庫管理系統,如果使用到了其他的數據庫管理系統,也同樣的使用SQL來操作。
2,MySQL
2.1 MySQL安裝
安裝環境:Win10 64位
軟件版本:MySQL 5.7.24 解壓版
2.1.1 下載
https://downloads.mysql.com/archives/community/
點開上面的鏈接就能看到如下界面:
選擇選擇和自己系統位數相對應的版本點擊右邊的Download,此時會進到另一個頁面,同樣在接近頁面底部的地方找到如下圖所示的位置:
不用理會上面的登錄和注冊按鈕,直接點擊 No thanks, just start my download. 就可以下載。
2.1.2 安裝(解壓)
下載完成后我們得到的是一個壓縮包,將其解壓,我們就可以得到MySQL 5.7.24的軟件本體了(就是一個文件夾),我們可以把它放在你想安裝的位置。
2.2 MySQL卸載
如果你想卸載MySQL,也很簡單。
右鍵開始菜單,選擇命令提示符(管理員),打開黑框。
至此,MySQL卸載完成!
2.3 MySQL配置
2.3.1 添加環境變量
環境變量里面有很多選項,這里我們只用到Path這個參數。為什么在初始化的開始要添加環境變量呢?
在黑框(即CMD)中輸入一個可執行程序的名字,Windows會先在環境變量中的Path所指的路徑中尋找一遍,如果找到了就直接執行,沒找到就在當前工作目錄找,如果還沒找到,就報錯。我們添加環境變量的目的就是能夠在任意一個黑框直接調用MySQL中的相關程序而不用總是修改工作目錄,大大簡化了操作。
右鍵此電腦→屬性,點擊高級系統設置
點擊環境變量
在系統變量中新建MYSQL_HOME
在系統變量中找到并雙擊Path
點擊新建
最后點擊確定。
如何驗證是否添加成功?
右鍵開始菜單(就是屏幕左下角),選擇命令提示符(管理員),打開黑框,敲入mysql,回車。
如果提示Can't connect to MySQL server on 'localhost'則證明添加成功;
如果提示mysql不是內部或外部命令,也不是可運行的程序或批處理文件則表示添加添加失敗,請重新檢查步驟并重試。
2.3.2 新建配置文件
新建一個文本文件,內容如下:
[mysql] default-character-set=utf8[mysqld] character-set-server=utf8 default-storage-engine=INNODB sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION把上面的文本文件另存為,在保存類型里選所有文件 (*.*),文件名叫my.ini,存放的路徑為MySQL的根目錄(例如我的是D:\software\mysql-5.7.24-winx64,根據自己的MySQL目錄位置修改)。
上面代碼意思就是配置數據庫的默認編碼集為utf-8和默認存儲引擎為INNODB。
2.3.3 初始化MySQL
在剛才的黑框中敲入mysqld --initialize-insecure,回車,稍微等待一會,如果出現沒有出現報錯信息(如下圖)則證明data目錄初始化沒有問題,此時再查看MySQL目錄下已經有data目錄生成。
mysqld --initialize-insecuretips:如果出現如下錯誤
是由于權限不足導致的,去C:\Windows\System32 下以管理員方式運行 cmd.exe
2.3.4 注冊MySQL服務
在黑框里敲入mysqld -install,回車。
mysqld -install現在你的計算機上已經安裝好了MySQL服務了。
MySQL服務器
2.3.5 啟動MySQL服務
在黑框里敲入net start mysql,回車。
net start mysql // 啟動mysql服務net stop mysql // 停止mysql服務2.3.6 修改默認賬戶密碼
在黑框里敲入mysqladmin -u root password 1234,這里的1234就是指默認管理員(即root賬戶)的密碼,可以自行修改成你喜歡的。
mysqladmin -u root password 1234至此,MySQL 5.7 解壓版安裝完畢!
2.4 MySQL登陸和退出
2.4.1 登陸
右鍵開始菜單,選擇命令提示符,打開黑框。
在黑框中輸入,mysql -uroot -p1234,回車,出現下圖且左下角為mysql>,則登錄成功。
到這里你就可以開始你的MySQL之旅了!
登陸參數:
mysql -u用戶名 -p密碼 -h要連接的mysql服務器的ip地址(默認127.0.0.1) -P端口號(默認3306)2.4.2 退出
退出mysql:
exit quit2.5 MySQL數據模型
關系型數據庫:
關系型數據庫是建立在關系模型基礎上的數據庫,簡單說,關系型數據庫是由多張能互相連接的 二維表 組成的數據庫
如下圖,訂單信息表 和 客戶信息表 都是有行有列二維表我們將這樣的稱為關系型數據庫。
接下來看關系型數據庫的優點:
- 都是使用表結構,格式一致,易于維護。
- 使用通用的 SQL 語言操作,使用方便,可用于復雜查詢。
- 關系型數據庫都可以通過SQL進行操作,所以使用方便。
- 復雜查詢。現在需要查詢001號訂單數據,我們可以看到該訂單是1號客戶的訂單,而1號訂單是李聰這個客戶。以后也可以在一張表中進行統計分析等操作。
- 數據存儲在磁盤中,安全。
數據模型:
如上圖,我們通過客戶端可以通過數據庫管理系統創建數據庫,在數據庫中創建表,在表中添加數據。創建的每一個數據庫對應到磁盤上都是一個文件夾。比如可以通過SQL語句創建一個數據庫(數據庫名稱為db1),語句如下。
create database dn1;我們可以在數據庫安裝目錄下的data目錄下看到多了一個 db1 的文件夾。所以,在MySQL中一個數據庫對應到磁盤上的一個文件夾。
而一個數據庫下可以創建多張表,我們到MySQL中自帶的mysql數據庫的文件夾目錄下:
而上圖中右邊的 db.frm 是表文件,db.MYD 是數據文件,通過這兩個文件就可以查詢到數據展示成二維表的效果。
3,SQL概述
了解了數據模型后,接下來我們就學習SQL語句,通過SQL語句對數據庫、表、數據進行增刪改查操作。
3.1 SQL簡介
- 英文:Structured Query Language,簡稱 SQL
- 結構化查詢語言,一門操作關系型數據庫的編程語言
- 定義操作所有關系型數據庫的統一標準
- 對于同一個需求,每一種數據庫操作的方式可能會存在一些不一樣的地方,我們稱為“方言”
3.2 通用語法
-
SQL 語句可以單行或多行書寫,以分號結尾。
如上,以分號結尾才是一個完整的sql語句。
-
MySQL 數據庫的 SQL 語句不區分大小寫,關鍵字建議使用大寫。
同樣的一條sql語句寫成下圖的樣子,一樣可以運行處結果。
-
注釋
- 單行注釋: – 注釋內容 或 #注釋內容(MySQL 特有)
注意:使用-- 添加單行注釋時,–后面一定要加空格,而#沒有要求。
- 多行注釋: /* 注釋 */
3.3 SQL分類
-
DDL(Data Definition Language) : 數據定義語言,用來定義數據庫對象:數據庫,表,列等
DDL簡單理解就是用來操作數據庫,表等
-
DML(Data Manipulation Language) 數據操作語言,用來對數據庫中表的數據進行增刪改
DML簡單理解就對表中數據進行增刪改
-
DQL(Data Query Language) 數據查詢語言,用來查詢數據庫中表的記錄(數據)
DQL簡單理解就是對數據進行查詢操作。從數據庫表中查詢到我們想要的數據。
-
DCL(Data Control Language) 數據控制語言,用來定義數據庫的訪問權限和安全級別,及創建用戶
DML簡單理解就是對數據庫進行權限控制。比如我讓某一個數據庫表只能讓某一個用戶進行操作等。
注意: 以后我們最常操作的是 DML 和 DQL ,因為我們開發中最常操作的就是數據。
4,DDL:操作數據庫
我們先來學習DDL來操作數據庫。而操作數據庫主要就是對數據庫的增刪查操作。
4.1 查詢
查詢所有的數據庫
SHOW DATABASES;運行上面語句效果如下:
上述查詢到的是的這些數據庫是mysql安裝好自帶的數據庫,我們以后不要操作這些數據庫。
4.2 創建數據庫
- 創建數據庫:
運行語句效果如下:
而在創建數據庫的時候,我并不知道db1數據庫有沒有創建,直接再次創建名為db1的數據庫就會出現錯誤。
為了避免上面的錯誤,在創建數據庫的時候先做判斷,如果不存在再創建。
- 創建數據庫(判斷,如果不存在則創建)
運行語句效果如下:
從上面的效果可以看到雖然db1數據庫已經存在,再創建db1也沒有報錯,而創建db2數據庫則創建成功。
4.3 刪除數據庫
- 刪除數據庫
- 刪除數據庫(判斷,如果存在則刪除)
運行語句效果如下:
4.4 使用數據庫
數據庫創建好了,要在數據庫中創建表,得先明確在哪兒個數據庫中操作,此時就需要使用數據庫。
- 使用數據庫
- 查看當前使用的數據庫
運行語句效果如下:
5,DDL:操作表
操作表也就是對表進行增(Create)刪(Retrieve)改(Update)查(Delete)。
5.1 查詢表
- 查詢當前數據庫下所有表名稱
我們創建的數據庫中沒有任何表,因此我們進入mysql自帶的mysql數據庫,執行上述語句查看
- 查詢表結構
查看mysql數據庫中func表的結構,運行語句如下:
5.2 創建表
- 創建表
注意:最后一行末尾,不能加逗號
知道了創建表的語句,那么我們創建創建如下結構的表
create table tb_user (id int,username varchar(20),password varchar(32) );運行語句如下:
5.3 數據類型
MySQL 支持多種類型,可以分為三類:
-
數值
tinyint : 小整數型,占一個字節 int : 大整數類型,占四個字節eg : age int double : 浮點類型使用格式: 字段名 double(總長度,小數點后保留的位數)eg : score double(5,2) -
日期
date : 日期值。只包含年月日eg :birthday date : datetime : 混合日期和時間值。包含年月日時分秒 -
字符串
char : 定長字符串。優點:存儲性能高缺點:浪費空間eg : name char(10) 如果存儲的數據字符個數不足10個,也會占10個的空間 varchar : 變長字符串。優點:節約空間缺點:存儲性能底eg : name varchar(10) 如果存儲的數據字符個數不足10個,那就數據字符個數是幾就占幾個的空間
注意:其他類型參考資料中的《MySQL數據類型].xlsx》
案例:
需求:設計一張學生表,請注重數據類型、長度的合理性1. 編號2. 姓名,姓名最長不超過10個漢字3. 性別,因為取值只有兩種可能,因此最多一個漢字4. 生日,取值為年月日5. 入學成績,小數點后保留兩位6. 郵件地址,最大長度不超過 647. 家庭聯系電話,不一定是手機號碼,可能會出現 - 等字符8. 學生狀態(用數字表示,正常、休學、畢業...)語句設計如下:
create table student (id int,name varchar(10),gender char(1),birthday date,score double(5,2),email varchar(15),tel varchar(15),status tinyint );5.4 刪除表
- 刪除表
- 刪除表時判斷表是否存在
運行語句效果如下:
5.5 修改表
- 修改表名
- 添加一列
- 修改數據類型
- 修改列名和數據類型
- 刪除列
6,navicat使用
通過上面的學習,我們發現在命令行中寫sql語句特別不方便,尤其是編寫創建表的語句,我們只能在記事本上寫好后直接復制到命令行進行執行。那么有沒有剛好的工具提供給我們進行使用呢? 有。
6.1 navicat概述
- Navicat for MySQL 是管理和開發 MySQL 或 MariaDB 的理想解決方案。
- 這套全面的前端工具為數據庫管理、開發和維護提供了一款直觀而強大的圖形界面。
- 官網: http://www.navicat.com.cn
6.2 navicat安裝
參考 : 資料\navicat安裝包\navicat_mysql_x86\navicat安裝步驟.md
6.3 navicat使用
6.3.1 建立和mysql服務的連接
第一步: 點擊連接,選擇MySQL
第二步:填寫連接數據庫必要的信息
以上操作沒有問題就會出現如下圖所示界面:
6.3.2 操作
連接成功后就能看到如下圖界面:
- 修改表結構
通過下圖操作修改表結構:
點擊了設計表后即出現如下圖所示界面,在圖中紅框中直接修改字段名,類型等信息:
- 編寫SQL語句并執行
按照如下圖所示進行操作即可書寫SQL語句并執行sql語句。
7,DML
DML主要是對數據進行增(insert)刪(delete)改(update)操作。
7.1 添加數據
- 給指定列添加數據
- 給全部列添加數據
- 批量添加數據
- 練習
為了演示以下的增刪改操作是否操作成功,故先將查詢所有數據的語句介紹給大家:
select * from stu; -- 給指定列添加數據 INSERT INTO stu (id, NAME) VALUES (1, '張三'); -- 給所有列添加數據,列名的列表可以省略的 INSERT INTO stu (id,NAME,sex,birthday,score,email,tel,STATUS) VALUES (2,'李四','男','1999-11-11',88.88,'lisi@itcast.cn','13888888888',1);INSERT INTO stu VALUES (2,'李四','男','1999-11-11',88.88,'lisi@itcast.cn','13888888888',1);-- 批量添加數據 INSERT INTO stu VALUES (2,'李四','男','1999-11-11',88.88,'lisi@itcast.cn','13888888888',1),(2,'李四','男','1999-11-11',88.88,'lisi@itcast.cn','13888888888',1),(2,'李四','男','1999-11-11',88.88,'lisi@itcast.cn','13888888888',1);7.2 修改數據
- 修改表數據
注意:
-
練習
-
將張三的性別改為女
update stu set sex = '女' where name = '張三'; -
將張三的生日改為 1999-12-12 分數改為99.99
update stu set birthday = '1999-12-12', score = 99.99 where name = '張三'; -
注意:如果update語句沒有加where條件,則會將表中所有數據全部修改!
update stu set sex = '女';上面語句的執行完后查詢到的結果是:
-
7.3 刪除數據
- 刪除數據
- 練習
8,DQL
先介紹查詢的完整語法:
SELECT 字段列表 FROM 表名列表 WHERE 條件列表 GROUP BY分組字段 HAVING分組后條件 ORDER BY排序字段 LIMIT分頁限定演示查詢的語句,先準備表及一些數據:
-- 刪除stu表 drop table if exists stu;-- 創建stu表 CREATE TABLE stu (id int, -- 編號name varchar(20), -- 姓名age int, -- 年齡sex varchar(5), -- 性別address varchar(100), -- 地址math double(5,2), -- 數學成績english double(5,2), -- 英語成績hire_date date -- 入學時間 );-- 添加數據 INSERT INTO stu(id,NAME,age,sex,address,math,english,hire_date) VALUES (1,'馬運',55,'男','杭州',66,78,'1995-09-01'), (2,'馬花疼',45,'女','深圳',98,87,'1998-09-01'), (3,'馬斯克',55,'男','香港',56,77,'1999-09-02'), (4,'柳白',20,'女','湖南',76,65,'1997-09-05'), (5,'柳青',20,'男','湖南',86,NULL,'1998-09-01'), (6,'劉德花',57,'男','香港',99,99,'1998-09-01'), (7,'張學右',22,'女','香港',99,99,'1998-09-01'), (8,'德瑪西亞',18,'男','南京',56,65,'1994-09-02');接下來咱們從最基本的查詢語句開始學起。
8.1 基礎查詢
8.1.1 語法
- 查詢多個字段
- 去除重復記錄
- 起別名
8.1.2 練習
-
查詢name、age兩列
select name,age from stu; -
查詢所有列的數據,列名的列表可以使用*替代
select * from stu;上面語句中的*不建議大家使用,因為在這寫*不方便我們閱讀sql語句。我們寫字段列表的話,可以添加注釋對每一個字段進行說明
而在上課期間為了簡約課程的時間,老師很多地方都會寫*。
-
查詢地址信息
select address from stu;執行上面語句結果如下:
從上面的結果我們可以看到有重復的數據,我們也可以使用 distinct 關鍵字去重重復數據。
-
去除重復記錄
select distinct address from stu; -
查詢姓名、數學成績、英語成績。并通過as給math和english起別名(as關鍵字可以省略)
select name,math as 數學成績,english as 英文成績 from stu; select name,math 數學成績,english 英文成績 from stu;
8.2 條件查詢
8.2.1 語法
SELECT 字段列表 FROM 表名 WHERE 條件列表;- 條件
條件列表可以使用以下運算符
8.2.2 條件查詢練習
-
查詢年齡大于20歲的學員信息
select * from stu where age > 20; -
查詢年齡大于等于20歲的學員信息
select * from stu where age >= 20; -
查詢年齡大于等于20歲 并且 年齡 小于等于 30歲 的學員信息
select * from stu where age >= 20 && age <= 30; select * from stu where age >= 20 and age <= 30;上面語句中 && 和 and 都表示并且的意思。建議使用 and 。
也可以使用 between … and 來實現上面需求
select * from stu where age BETWEEN 20 and 30; -
查詢入學日期在’1998-09-01’ 到 ‘1999-09-01’ 之間的學員信息
select * from stu where hire_date BETWEEN '1998-09-01' and '1999-09-01'; -
查詢年齡等于18歲的學員信息
select * from stu where age = 18; -
查詢年齡不等于18歲的學員信息
select * from stu where age != 18; select * from stu where age <> 18; -
查詢年齡等于18歲 或者 年齡等于20歲 或者 年齡等于22歲的學員信息
select * from stu where age = 18 or age = 20 or age = 22; select * from stu where age in (18,20 ,22); -
查詢英語成績為 null的學員信息
null值的比較不能使用 = 或者 != 。需要使用 is 或者 is not
select * from stu where english = null; -- 這個語句是不行的 select * from stu where english is null; select * from stu where english is not null;
8.2.3 模糊查詢練習
模糊查詢使用like關鍵字,可以使用通配符進行占位:
(1)_ : 代表單個任意字符
(2)% : 代表任意個數字符
-
查詢姓’馬’的學員信息
select * from stu where name like '馬%'; -
查詢第二個字是’花’的學員信息
select * from stu where name like '_花%'; -
查詢名字中包含 ‘德’ 的學員信息
select * from stu where name like '%德%';
8.3 排序查詢
8.3.1 語法
SELECT 字段列表 FROM 表名 ORDER BY 排序字段名1 [排序方式1],排序字段名2 [排序方式2] …;上述語句中的排序方式有兩種,分別是:
- ASC : 升序排列 (默認值)
- DESC : 降序排列
注意:如果有多個排序條件,當前邊的條件值一樣時,才會根據第二條件進行排序
8.3.2 練習
-
查詢學生信息,按照年齡升序排列
select * from stu order by age ; -
查詢學生信息,按照數學成績降序排列
select * from stu order by math desc ; -
查詢學生信息,按照數學成績降序排列,如果數學成績一樣,再按照英語成績升序排列
select * from stu order by math desc , english asc ;
8.4 聚合函數
8.4.1 概念
將一列數據作為一個整體,進行縱向計算。
如何理解呢?假設有如下表
現有一需求讓我們求表中所有數據的數學成績的總和。這就是對math字段進行縱向求和。
8.4.2 聚合函數分類
| count(列名) | 統計數量(一般選用不為null的列) |
| max(列名) | 最大值 |
| min(列名) | 最小值 |
| sum(列名) | 求和 |
| avg(列名) | 平均值 |
8.4.3 聚合函數語法
SELECT 聚合函數名(列名) FROM 表;注意:null 值不參與所有聚合函數運算
8.4.4 練習
-
統計班級一共有多少個學生
select count(id) from stu; select count(english) from stu;上面語句根據某個字段進行統計,如果該字段某一行的值為null的話,將不會被統計。所以可以在count(*) 來實現。* 表示所有字段數據,一行中也不可能所有的數據都為null,所以建議使用 count(*)
select count(*) from stu; -
查詢數學成績的最高分
select max(math) from stu; -
查詢數學成績的最低分
select min(math) from stu; -
查詢數學成績的總分
select sum(math) from stu; -
查詢數學成績的平均分
select avg(math) from stu; -
查詢英語成績的最低分
select min(english) from stu;
8.5 分組查詢
8.5.1 語法
SELECT 字段列表 FROM 表名 [WHERE 分組前條件限定] GROUP BY 分組字段名 [HAVING 分組后條件過濾];注意:分組之后,查詢的字段為聚合函數和分組字段,查詢其他字段無任何意義
8.5.2 練習
-
查詢男同學和女同學各自的數學平均分
select sex, avg(math) from stu group by sex;注意:分組之后,查詢的字段為聚合函數和分組字段,查詢其他字段無任何意義
select name, sex, avg(math) from stu group by sex; -- 這里查詢name字段就沒有任何意義 -
查詢男同學和女同學各自的數學平均分,以及各自人數
select sex, avg(math),count(*) from stu group by sex; -
查詢男同學和女同學各自的數學平均分,以及各自人數,要求:分數低于70分的不參與分組
select sex, avg(math),count(*) from stu where math > 70 group by sex; -
查詢男同學和女同學各自的數學平均分,以及各自人數,要求:分數低于70分的不參與分組,分組之后人數大于2個的
select sex, avg(math),count(*) from stu where math > 70 group by sex having count(*) > 2;
where 和 having 區別:
-
執行時機不一樣:where 是分組之前進行限定,不滿足where條件,則不參與分組,而having是分組之后對結果進行過濾。
-
可判斷的條件不一樣:where 不能對聚合函數進行判斷,having 可以。
8.6 分頁查詢
如下圖所示,大家在很多網站都見過類似的效果,如京東、百度、淘寶等。分頁查詢是將數據一頁一頁的展示給用戶看,用戶也可以通過點擊查看下一頁的數據。
接下來我們先說分頁查詢的語法。
8.6.1 語法
SELECT 字段列表 FROM 表名 LIMIT 起始索引 , 查詢條目數;注意: 上述語句中的起始索引是從0開始
8.6.2 練習
-
從0開始查詢,查詢3條數據
select * from stu limit 0 , 3; -
每頁顯示3條數據,查詢第1頁數據
select * from stu limit 0 , 3; -
每頁顯示3條數據,查詢第2頁數據
select * from stu limit 3 , 3; -
每頁顯示3條數據,查詢第3頁數據
select * from stu limit 6 , 3;
從上面的練習推導出起始索引計算公式:
起始索引 = (當前頁碼 - 1) * 每頁顯示的條數9,約束
上面表中可以看到表中數據存在一些問題:
-
id 列一般是用標示數據的唯一性的,而上述表中的id為1的有三條數據,并且 馬花疼 沒有id進行標示
-
柳白 這條數據的age列的數據是3000,而人也不可能活到3000歲
-
馬運 這條數據的math數學成績是-5,而數學學得再不好也不可能出現負分
-
柳青 這條數據的english列(英文成績)值為null,而成績即使沒考也得是0分
針對上述數據問題,我們就可以從數據庫層面在添加數據的時候進行限制,這個就是約束。
9.1 概念
-
約束是作用于表中列上的規則,用于限制加入表的數據
例如:我們可以給id列加約束,讓其值不能重復,不能為null值。
-
約束的存在保證了數據庫中數據的正確性、有效性和完整性
添加約束可以在添加數據的時候就限制不正確的數據,年齡是3000,數學成績是-5分這樣無效的數據,繼而保障數據的完整性。
9.2 分類
-
非空約束: 關鍵字是 NOT NULL
保證列中所有的數據不能有null值。
例如:id列在添加 馬花疼 這條數據時就不能添加成功。
-
唯一約束:關鍵字是 UNIQUE
保證列中所有數據各不相同。
例如:id列中三條數據的值都是1,這樣的數據在添加時是絕對不允許的。
-
主鍵約束: 關鍵字是 PRIMARY KEY
主鍵是一行數據的唯一標識,要求非空且唯一。一般我們都會給沒張表添加一個主鍵列用來唯一標識數據。
例如:上圖表中id就可以作為主鍵,來標識每條數據。那么這樣就要求數據中id的值不能重復,不能為null值。
-
檢查約束: 關鍵字是 CHECK
保證列中的值滿足某一條件。
例如:我們可以給age列添加一個范圍,最低年齡可以設置為1,最大年齡就可以設置為300,這樣的數據才更合理些。
注意:MySQL不支持檢查約束。
這樣是不是就沒辦法保證年齡在指定的范圍內了?從數據庫層面不能保證,以后可以在java代碼中進行限制,一樣也可以實現要求。
-
默認約束: 關鍵字是 DEFAULT
保存數據時,未指定值則采用默認值。
例如:我們在給english列添加該約束,指定默認值是0,這樣在添加數據時沒有指定具體值時就會采用默認給定的0。
-
外鍵約束: 關鍵字是 FOREIGN KEY
外鍵用來讓兩個表的數據之間建立鏈接,保證數據的一致性和完整性。
外鍵約束現在可能還不太好理解,后面我們會重點進行講解。
9.3 非空約束
-
概念
非空約束用于保證列中所有數據不能有NULL值
-
語法
-
添加約束
-- 創建表時添加非空約束 CREATE TABLE 表名(列名 數據類型 NOT NULL,… ); -- 建完表后添加非空約束 ALTER TABLE 表名 MODIFY 字段名 數據類型 NOT NULL; -
刪除約束
ALTER TABLE 表名 MODIFY 字段名 數據類型;
-
9.4 唯一約束
-
概念
唯一約束用于保證列中所有數據各不相同
-
語法
-
添加約束
-- 創建表時添加唯一約束 CREATE TABLE 表名(列名 數據類型 UNIQUE [AUTO_INCREMENT],-- AUTO_INCREMENT: 當不指定值時自動增長… ); CREATE TABLE 表名(列名 數據類型,…[CONSTRAINT] [約束名稱] UNIQUE(列名) ); -- 建完表后添加唯一約束 ALTER TABLE 表名 MODIFY 字段名 數據類型 UNIQUE; -
刪除約束
ALTER TABLE 表名 DROP INDEX 字段名;
-
9.5 主鍵約束
-
概念
主鍵是一行數據的唯一標識,要求非空且唯一
一張表只能有一個主鍵
-
語法
-
添加約束
-- 創建表時添加主鍵約束 CREATE TABLE 表名(列名 數據類型 PRIMARY KEY [AUTO_INCREMENT],… ); CREATE TABLE 表名(列名 數據類型,[CONSTRAINT] [約束名稱] PRIMARY KEY(列名) ); -- 建完表后添加主鍵約束 ALTER TABLE 表名 ADD PRIMARY KEY(字段名); -
刪除約束
ALTER TABLE 表名 DROP PRIMARY KEY;
-
9.6 默認約束
-
概念
保存數據時,未指定值則采用默認值
-
語法
-
添加約束
-- 創建表時添加默認約束 CREATE TABLE 表名(列名 數據類型 DEFAULT 默認值,… ); -- 建完表后添加默認約束 ALTER TABLE 表名 ALTER 列名 SET DEFAULT 默認值; -
刪除約束
ALTER TABLE 表名 ALTER 列名 DROP DEFAULT;
-
9.7 約束練習
根據需求,為表添加合適的約束
-- 員工表 CREATE TABLE emp (id INT, -- 員工id,主鍵且自增長ename VARCHAR(50), -- 員工姓名,非空且唯一joindate DATE, -- 入職日期,非空salary DOUBLE(7,2), -- 工資,非空bonus DOUBLE(7,2) -- 獎金,如果沒有將近默認為0 );上面一定給出了具體的要求,我們可以根據要求創建這張表,并為每一列添加對應的約束。建表語句如下:
DROP TABLE IF EXISTS emp;-- 員工表 CREATE TABLE emp (id INT PRIMARY KEY, -- 員工id,主鍵且自增長ename VARCHAR(50) NOT NULL UNIQUE, -- 員工姓名,非空并且唯一joindate DATE NOT NULL , -- 入職日期,非空salary DOUBLE(7,2) NOT NULL , -- 工資,非空bonus DOUBLE(7,2) DEFAULT 0 -- 獎金,如果沒有獎金默認為0 );通過上面語句可以創建帶有約束的 emp 表,約束能不能發揮作用呢。接下來我們一一進行驗證,先添加一條沒有問題的數據
INSERT INTO emp(id,ename,joindate,salary,bonus) values(1,'張三','1999-11-11',8800,5000);- 驗證主鍵約束,非空且唯一
執行結果如下:
從上面的結果可以看到,字段 id 不能為null。那我們重新添加一條數據,如下:
INSERT INTO emp(id,ename,joindate,salary,bonus) values(1,'張三','1999-11-11',8800,5000);執行結果如下:
從上面結果可以看到,1這個值重復了。所以主鍵約束是用來限制數據非空且唯一的。那我們再添加一條符合要求的數據
INSERT INTO emp(id,ename,joindate,salary,bonus) values(2,'李四','1999-11-11',8800,5000);執行結果如下:
- 驗證非空約束
執行結果如下:
從上面結果可以看到,ename 字段的非空約束生效了。
- 驗證唯一約束
執行結果如下:
從上面結果可以看到,ename 字段的唯一約束生效了。
- 驗證默認約束
執行完上面語句后查詢表中數據,如下圖可以看到王五這條數據的bonus列就有了默認值0。
注意:默認約束只有在不給值時才會采用默認值。如果給了null,那值就是null值。
如下:
INSERT INTO emp(id,ename,joindate,salary,bonus) values(4,'趙六','1999-11-11',8800,null);執行完上面語句后查詢表中數據,如下圖可以看到趙六這條數據的bonus列的值是null。
- 驗證自動增長: auto_increment 當列是數字類型 并且唯一約束
重新創建 emp 表,并給id列添
加自動增長
接下來給emp添加數據,分別驗證不給id列添加值以及給id列添加null值,id列的值會不會自動增長:
INSERT INTO emp(ename,joindate,salary,bonus) values('趙六','1999-11-11',8800,null); INSERT INTO emp(id,ename,joindate,salary,bonus) values(null,'趙六2','1999-11-11',8800,null); INSERT INTO emp(id,ename,joindate,salary,bonus) values(null,'趙六3','1999-11-11',8800,null);9.8 外鍵約束
9.8.1 概述
外鍵用來讓兩個表的數據之間建立鏈接,保證數據的一致性和完整性。
如何理解上面的概念呢?如下圖有兩張表,員工表和部門表:
員工表中的dep_id字段是部門表的id字段關聯,也就是說1號學生張三屬于1號部門研發部的員工。現在我要刪除1號部門,就會出現錯誤的數據(員工表中屬于1號部門的數據)。而我們上面說的兩張表的關系只是我們認為它們有關系,此時需要通過外鍵讓這兩張表產生數據庫層面的關系,這樣你要刪除部門表中的1號部門的數據將無法刪除。
9.8.2 語法
- 添加外鍵約束
- 刪除外鍵約束
9.8.3 練習
根據上述語法創建員工表和部門表,并添加上外鍵約束:
-- 刪除表 DROP TABLE IF EXISTS emp; DROP TABLE IF EXISTS dept;-- 部門表 CREATE TABLE dept(id int primary key auto_increment,dep_name varchar(20),addr varchar(20) ); -- 員工表 CREATE TABLE emp(id int primary key auto_increment,name varchar(20),age int,dep_id int,-- 添加外鍵 dep_id,關聯 dept 表的id主鍵CONSTRAINT fk_emp_dept FOREIGN KEY(dep_id) REFERENCES dept(id) );添加數據
-- 添加 2 個部門 insert into dept(dep_name,addr) values ('研發部','廣州'),('銷售部', '深圳');-- 添加員工,dep_id 表示員工所在的部門 INSERT INTO emp (NAME, age, dep_id) VALUES ('張三', 20, 1), ('李四', 20, 1), ('王五', 20, 1), ('趙六', 20, 2), ('孫七', 22, 2), ('周八', 18, 2);此時刪除 研發部 這條數據,會發現無法刪除。
刪除外鍵
alter table emp drop FOREIGN key fk_emp_dept;重新添加外鍵
alter table emp add CONSTRAINT fk_emp_dept FOREIGN key(dep_id) REFERENCES dept(id);10,數據庫設計
10.1 數據庫設計簡介
-
軟件的研發步驟
-
數據庫設計概念
- 數據庫設計就是根據業務系統的具體需求,結合我們所選用的DBMS,為這個業務系統構造出最優的數據存儲模型。
- 建立數據庫中的表結構以及表與表之間的關聯關系的過程。
- 有哪些表?表里有哪些字段?表和表之間有什么關系?
-
數據庫設計的步驟
-
需求分析(數據是什么? 數據具有哪些屬性? 數據與屬性的特點是什么)
-
邏輯分析(通過ER圖對數據庫進行邏輯建模,不需要考慮我們所選用的數據庫管理系統)
如下圖就是ER(Entity/Relation)圖:
-
物理設計(根據數據庫自身的特點把邏輯設計轉換為物理設計)
-
維護設計(9.對新的需求進行建表;10.表優化)
-
-
表關系
-
一對一
- 如:用戶 和 用戶詳情
- 一對一關系多用于表拆分,將一個實體中經常使用的字段放一張表,不經常使用的字段放另一張表,用于提升查詢性能
上圖左邊是用戶的詳細信息,而我們真正在展示用戶信息時最長用的則是上圖右邊紅框所示,所以我們會將詳細信息查分成兩周那個表。
-
一對多
-
如:部門 和 員工
-
一個部門對應多個員工,一個員工對應一個部門。如下圖:
-
-
多對多
-
如:商品 和 訂單
-
一個商品對應多個訂單,一個訂單包含多個商品。如下圖:
-
-
10.2 表關系(一對多)
-
一對多
- 如:部門 和 員工
- 一個部門對應多個員工,一個員工對應一個部門。
-
實現方式
在多的一方建立外鍵,指向一的一方的主鍵
-
案例
我們還是以 員工表 和 部門表 舉例:
在這里插入圖片描述
經過分析發現,員工表屬于多的一方,而部門表屬于一的一方,此時我們會在員工表中添加一列(dep_id),指向于部門表的主鍵(id):
建表語句如下:
-- 刪除表 DROP TABLE IF EXISTS tb_emp; DROP TABLE IF EXISTS tb_dept;-- 部門表 CREATE TABLE tb_dept(id int primary key auto_increment,dep_name varchar(20),addr varchar(20) ); -- 員工表 CREATE TABLE tb_emp(id int primary key auto_increment,name varchar(20),age int,dep_id int,-- 添加外鍵 dep_id,關聯 dept 表的id主鍵CONSTRAINT fk_emp_dept FOREIGN KEY(dep_id) REFERENCES tb_dept(id) );查看表結構模型圖:
10.3 表關系(多對多)
-
多對多
- 如:商品 和 訂單
- 一個商品對應多個訂單,一個訂單包含多個商品
-
實現方式
建立第三張中間表,中間表至少包含兩個外鍵,分別關聯兩方主鍵
-
案例
我們以 訂單表 和 商品表 舉例:
經過分析發現,訂單表和商品表都屬于多的一方,此時需要創建一個中間表,在中間表中添加訂單表的外鍵和商品表的外鍵指向兩張表的主鍵:
建表語句如下:
-- 刪除表 DROP TABLE IF EXISTS tb_order_goods; DROP TABLE IF EXISTS tb_order; DROP TABLE IF EXISTS tb_goods;-- 訂單表 CREATE TABLE tb_order(id int primary key auto_increment,payment double(10,2),payment_type TINYINT,status TINYINT );-- 商品表 CREATE TABLE tb_goods(id int primary key auto_increment,title varchar(100),price double(10,2) );-- 訂單商品中間表 CREATE TABLE tb_order_goods(id int primary key auto_increment,order_id int,goods_id int,count int );-- 建完表后,添加外鍵 alter table tb_order_goods add CONSTRAINT fk_order_id FOREIGN key(order_id) REFERENCES tb_order(id); alter table tb_order_goods add CONSTRAINT fk_goods_id FOREIGN key(goods_id) REFERENCES tb_goods(id);查看表結構模型圖:
10.4 表關系(一對一)
-
一對一
- 如:用戶 和 用戶詳情
- 一對一關系多用于表拆分,將一個實體中經常使用的字段放一張表,不經常使用的字段放另一張表,用于提升查詢性能
-
實現方式
在任意一方加入外鍵,關聯另一方主鍵,并且設置外鍵為唯一(UNIQUE)
-
案例
我們以 用戶表 舉例:
而在真正使用過程中發現 id、photo、nickname、age、gender 字段比較常用,此時就可以將這張表查分成兩張表。
?
?
? 建表語句如下:
create table tb_user_desc (id int primary key auto_increment,city varchar(20),edu varchar(10),income int,status char(2),des varchar(100) );create table tb_user (id int primary key auto_increment,photo varchar(100),nickname varchar(50),age int,gender char(1),desc_id int unique,-- 添加外鍵CONSTRAINT fk_user_desc FOREIGN KEY(desc_id) REFERENCES tb_user_desc(id) );? 查看表結構模型圖:
10.5 數據庫設計案例
根據下圖設計表及表和表之間的關系:
經過分析,我們分為 專輯表 曲目表 短評表 用戶表 4張表。
一個專輯可以有多個曲目,一個曲目只能屬于某一張專輯,所以專輯表和曲目表的關系是一對多。
一個專輯可以被多個用戶進行評論,一個用戶可以對多個專輯進行評論,所以專輯表和用戶表的關系是 多對多。
一個用戶可以發多個短評,一個短評只能是某一個人發的,所以用戶表和短評表的關系是 一對多。
11,多表查詢
多表查詢顧名思義就是從多張表中一次性的查詢出我們想要的數據。我們通過具體的sql給他們演示,先準備環境
DROP TABLE IF EXISTS emp; DROP TABLE IF EXISTS dept;# 創建部門表CREATE TABLE dept(did INT PRIMARY KEY AUTO_INCREMENT,dname VARCHAR(20));# 創建員工表CREATE TABLE emp (id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(10),gender CHAR(1), -- 性別salary DOUBLE, -- 工資join_date DATE, -- 入職日期dep_id INT,FOREIGN KEY (dep_id) REFERENCES dept(did) -- 外鍵,關聯部門表(部門表的主鍵));-- 添加部門數據INSERT INTO dept (dNAME) VALUES ('研發部'),('市場部'),('財務部'),('銷售部');-- 添加員工數據INSERT INTO emp(NAME,gender,salary,join_date,dep_id) VALUES('孫悟空','男',7200,'2013-02-24',1),('豬八戒','男',3600,'2010-12-02',2),('唐僧','男',9000,'2008-08-08',2),('白骨精','女',5000,'2015-10-07',3),('蜘蛛精','女',4500,'2011-03-14',1),('小白龍','男',2500,'2011-02-14',null);執行下面的多表查詢語句
select * from emp , dept; -- 從emp和dept表中查詢所有的字段數據結果如下:
從上面的結果我們看到有一些無效的數據,如 孫悟空 這個員工屬于1號部門,但也同時關聯的2、3、4號部門。所以我們要通過限制員工表中的 dep_id 字段的值和部門表 did 字段的值相等來消除這些無效的數據,
select * from emp , dept where emp.dep_id = dept.did;執行后結果如下:
上面語句就是連接查詢,那么多表查詢都有哪些呢?
- 連接查詢
-
內連接查詢 :相當于查詢AB交集數據
-
外連接查詢
- 左外連接查詢 :相當于查詢A表所有數據和交集部門數據
- 右外連接查詢 : 相當于查詢B表所有數據和交集部分數據
-
子查詢
11.1 內連接查詢
- 語法
內連接相當于查詢 A B 交集數據
-
案例
-
隱式內連接
SELECT* FROMemp,dept WHEREemp.dep_id = dept.did;執行上述語句結果如下:
-
-
查詢 emp的 name, gender,dept表的dname
SELECTemp. NAME,emp.gender,dept.dname FROMemp,dept WHEREemp.dep_id = dept.did;執行語句結果如下:
- 上面語句中使用表名指定字段所屬有點麻煩,sql也支持給表指別名,上述語句可以改進為
-
顯式內連接
select * from emp inner join dept on emp.dep_id = dept.did; -- 上面語句中的inner可以省略,可以書寫為如下語句 select * from emp join dept on emp.dep_id = dept.did;執行結果如下:
11.2 外連接查詢
-
語法
-- 左外連接 SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 條件;-- 右外連接 SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 條件;左外連接:相當于查詢A表所有數據和交集部分數據
右外連接:相當于查詢B表所有數據和交集部分數據
-
案例
-
查詢emp表所有數據和對應的部門信息(左外連接)
select * from emp left join dept on emp.dep_id = dept.did;執行語句結果如下:
-
-
查詢dept表所有數據和對應的員工信息(右外連接)
select * from emp right join dept on emp.dep_id = dept.did;執行語句結果如下:
結果顯示查詢到了右表(dept)中所有的數據及兩張表能關聯的數據。
要查詢出部門表中所有的數據,也可以通過左外連接實現,只需要將兩個表的位置進行互換:
select * from dept left join emp on emp.dep_id = dept.did;
11.3 子查詢
-
概念
查詢中嵌套查詢,稱嵌套查詢為子查詢。
什么是查詢中嵌套查詢呢?我們通過一個例子來看:
需求:查詢工資高于豬八戒的員工信息。
來實現這個需求,我們就可以通過二步實現,第一步:先查詢出來 豬八戒的工資
select salary from emp where name = '豬八戒'第二步:查詢工資高于豬八戒的員工信息
select * from emp where salary > 3600;第二步中的3600可以通過第一步的sql查詢出來,所以將3600用第一步的sql語句進行替換
select * from emp where salary > (select salary from emp where name = '豬八戒');這就是查詢語句中嵌套查詢語句。
-
子查詢根據查詢結果不同,作用不同
- 子查詢語句結果是單行單列,子查詢語句作為條件值,使用 = != > < 等進行條件判斷
- 子查詢語句結果是多行單列,子查詢語句作為條件值,使用 in 等關鍵字進行條件判斷
- 子查詢語句結果是多行多列,子查詢語句作為虛擬表
-
案例
-
查詢 ‘財務部’ 和 ‘市場部’ 所有的員工信息
-- 查詢 '財務部' 或者 '市場部' 所有的員工的部門did select did from dept where dname = '財務部' or dname = '市場部';select * from emp where dep_id in (select did from dept where dname = '財務部' or dname = '市場部'); -
查詢入職日期是 ‘2011-11-11’ 之后的員工信息和部門信息
-- 查詢入職日期是 '2011-11-11' 之后的員工信息 select * from emp where join_date > '2011-11-11' ; -- 將上面語句的結果作為虛擬表和dept表進行內連接查詢 select * from (select * from emp where join_date > '2011-11-11' ) t1, dept where t9.dep_id = dept.did;
-
11.4 案例
- 環境準備:
-
需求
-
查詢所有員工信息。查詢員工編號,員工姓名,工資,職務名稱,職務描述
/*分析:9. 員工編號,員工姓名,工資 信息在emp 員工表中10. 職務名稱,職務描述 信息在 job 職務表中11. job 職務表 和 emp 員工表 是 一對多的關系 emp.job_id = job.id */ -- 方式一 :隱式內連接 SELECTemp.id,emp.ename,emp.salary,job.jname,job.description FROMemp,job WHEREemp.job_id = job.id;-- 方式二 :顯式內連接 SELECTemp.id,emp.ename,emp.salary,job.jname,job.description FROMemp INNER JOIN job ON emp.job_id = job.id; -
查詢員工編號,員工姓名,工資,職務名稱,職務描述,部門名稱,部門位置
/*分析:9. 員工編號,員工姓名,工資 信息在emp 員工表中10. 職務名稱,職務描述 信息在 job 職務表中11. job 職務表 和 emp 員工表 是 一對多的關系 emp.job_id = job.id4. 部門名稱,部門位置 來自于 部門表 dept5. dept 和 emp 一對多關系 dept.id = emp.dept_id */-- 方式一 :隱式內連接 SELECTemp.id,emp.ename,emp.salary,job.jname,job.description,dept.dname,dept.loc FROMemp,job,dept WHEREemp.job_id = job.idand dept.id = emp.dept_id ;-- 方式二 :顯式內連接 SELECTemp.id,emp.ename,emp.salary,job.jname,job.description,dept.dname,dept.loc FROMemp INNER JOIN job ON emp.job_id = job.id INNER JOIN dept ON dept.id = emp.dept_id -
查詢員工姓名,工資,工資等級
/*分析:9. 員工姓名,工資 信息在emp 員工表中10. 工資等級 信息在 salarygrade 工資等級表中11. emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary */ SELECTemp.ename,emp.salary,t10.* FROMemp,salarygrade t2 WHEREemp.salary >= t10.losalary AND emp.salary <= t10.hisalary -
查詢員工姓名,工資,職務名稱,職務描述,部門名稱,部門位置,工資等級
/*分析:9. 員工編號,員工姓名,工資 信息在emp 員工表中10. 職務名稱,職務描述 信息在 job 職務表中11. job 職務表 和 emp 員工表 是 一對多的關系 emp.job_id = job.id12. 部門名稱,部門位置 來自于 部門表 dept5. dept 和 emp 一對多關系 dept.id = emp.dept_id6. 工資等級 信息在 salarygrade 工資等級表中7. emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary */ SELECTemp.id,emp.ename,emp.salary,job.jname,job.description,dept.dname,dept.loc,t10.grade FROMemp INNER JOIN job ON emp.job_id = job.id INNER JOIN dept ON dept.id = emp.dept_id INNER JOIN salarygrade t2 ON emp.salary BETWEEN t10.losalary and t10.hisalary; -
查詢出部門編號、部門名稱、部門位置、部門人數
/*分析:9. 部門編號、部門名稱、部門位置 來自于部門 dept 表10. 部門人數: 在emp表中 按照dept_id 進行分組,然后count(*)統計數量11. 使用子查詢,讓部門表和分組后的表進行內連接 */ -- 根據部門id分組查詢每一個部門id和員工數 select dept_id, count(*) from emp group by dept_id;SELECTdept.id,dept.dname,dept.loc,t9.count FROMdept,(SELECTdept_id,count(*) countFROMempGROUP BYdept_id) t1 WHEREdept.id = t9.dept_id
12,事務
12.1 概述
數據庫的事務(Transaction)是一種機制、一個操作序列,包含了一組數據庫操作命令。
事務把所有的命令作為一個整體一起向系統提交或撤銷操作請求,即這一組數據庫命令要么同時成功,要么同時失敗。
事務是一個不可分割的工作邏輯單元。
這些概念不好理解,接下來舉例說明,如下圖有一張表
張三和李四賬戶中各有100塊錢,現李四需要轉換500塊錢給張三,具體的轉賬操作為
- 第一步:查詢李四賬戶余額
- 第二步:從李四賬戶金額 -500
- 第三步:給張三賬戶金額 +500
現在假設在轉賬過程中第二步完成后出現了異常第三步沒有執行,就會造成李四賬戶金額少了500,而張三金額并沒有多500;這樣的系統是有問題的。如果解決呢?使用事務可以解決上述問題
從上圖可以看到在轉賬前開啟事務,如果出現了異常回滾事務,三步正常執行就提交事務,這樣就可以完美解決問題。
12.2 語法
-
開啟事務
START TRANSACTION; 或者 BEGIN; -
提交事務
commit; -
回滾事務
rollback;
12.3 代碼驗證
-
環境準備
DROP TABLE IF EXISTS account;-- 創建賬戶表 CREATE TABLE account(id int PRIMARY KEY auto_increment,name varchar(10),money double(10,2) );-- 添加數據 INSERT INTO account(name,money) values('張三',1000),('李四',1000); -
不加事務演示問題
-- 轉賬操作 -- 9. 查詢李四賬戶金額是否大于500-- 10. 李四賬戶 -500 UPDATE account set money = money - 500 where name = '李四';出現異常了... -- 此處不是注釋,在整體執行時會出問題,后面的sql則不執行 -- 11. 張三賬戶 +500 UPDATE account set money = money + 500 where name = '張三';整體執行結果肯定會出問題,我們查詢賬戶表中數據,發現李四賬戶少了500。
-
添加事務sql如下:
-- 開啟事務 BEGIN; -- 轉賬操作 -- 9. 查詢李四賬戶金額是否大于500-- 10. 李四賬戶 -500 UPDATE account set money = money - 500 where name = '李四';出現異常了... -- 此處不是注釋,在整體執行時會出問題,后面的sql則不執行 -- 11. 張三賬戶 +500 UPDATE account set money = money + 500 where name = '張三';-- 提交事務 COMMIT;-- 回滾事務 ROLLBACK;上面sql中的執行成功進選擇執行提交事務,而出現問題則執行回滾事務的語句。以后我們肯定不可能這樣操作,而是在java中進行操作,在java中可以抓取異常,沒出現異常提交事務,出現異常回滾事務。
12.4 事務的四大特征
-
原子性(Atomicity): 事務是不可分割的最小操作單位,要么同時成功,要么同時失敗
-
一致性(Consistency) :事務完成時,必須使所有的數據都保持一致狀態
-
隔離性(Isolation) :多個事務之間,操作的可見性
-
持久性(Durability) :事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的
說明:
mysql中事務是自動提交的。
也就是說我們不添加事務執行sql語句,語句執行完畢會自動的提交事務。
可以通過下面語句查詢默認提交方式:
SELECT @@autocommit;查詢到的結果是1 則表示自動提交,結果是0表示手動提交。當然也可以通過下面語句修改提交方式
set @@autocommit = 0;總結
以上是生活随笔為你收集整理的MYSQL数据库详解-从零入门,一篇正式入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CMakeList常用变量
- 下一篇: 宝马ETK数据提取导出MySQL