数据库学习笔记1
0407
數據庫學習筆記
- 附錄:
- 〇、視頻課鏈接
- 一、初識MySQL
- 1.為什么學習數據庫?
- 2.什么是數據庫?
- 3.數據庫總覽(分類)☆☆☆
- 4.什么是DBMS
- 5.安裝MySQL
- 6.安裝可視化工具SQLyog
- 7.用 `SQLyog` 創建數據庫 和 創建表
- ①創建數據庫school
- ②創建表
- ③查看表(打開表)
- ④小結:
- ⑤注釋 + 運行單行代碼
- 8.用命令行連接數據庫
- 幾個基本的數據庫操作命令
- 9.數據庫的基本知識
- 10.結構化查詢語句分類
- 二、操作數據庫和數據表(創建、刪除、使用、顯示、修改)
- 2.1 命令行操作數據庫(創建數據庫、刪除數據庫、使用數據庫、顯示數據庫)☆☆☆
- 2.2 數據字段 的 類型 和 屬性(重要)
- 1.列名:
- 2.數據類型(重要):
- ①數值類型(int 和 decimal) 和 字符串(varchar):
- ②日期和時間型數值類型(datetime) 和 NULL值:
- 3.長度:
- 4.默認:
- 5.主鍵:
- 6.非空(NOT NULL):
- 7.Unsigned:
- 8.自增(Auto_InCrement):
- 9.Zerofill:
- 10.更新:
- 11.注釋:
- 2.3 每一個表都必須存在以下五個字段
- 2.4 創建數據表(CREATE TABLE)☆☆☆
- 2.4.1 看個例子
- 2.4.2 創建表的格式:
- 2.4.3 補充:數據表的 引擎(類型) 和 字符集
- 2.5 修改表、刪除表
- 2.5.1 修改數據表(ALTER TABLE)☆☆☆
- 2.5.2 刪除數據表(DROP TABLE)☆☆☆
- 三、MySQL數據管理
- 3.1 數據庫級別的外鍵(了解即可)
- 3.2 DML語言(增、刪、改---重要!全部記住)☆☆☆
- 3.3 添加 --- INSERT INTO ☆☆☆
- 1. 插入操作的格式 和 注意事項
- 2. 先創建兩個表:
- 3. 對表grade進行插入操作:
- 4. 對表student進行插入操作:
- 3.4 修改 --- UPDATE ☆☆☆
- 3.5 刪除 --- DELETE FROM ☆☆☆
- DELETE FROM 和 TRUNCATE 的區別
- 四、DQL查詢數據(最重點!!!)
- SELECT語法 --> 27.SELECT小結
- 預備工作:16-20的數據庫代碼:
- 16. 查詢某個字段select 和 給字段起別名as
- 17. 去重復distinct 及 數據庫中的表達式
- 18. where子句之邏輯運算符
- 19. 模糊查詢操作符☆☆☆
- 20. 聯表查詢
- 21. 自連接
- 22. 分頁limit 和 排序order by
- 排序 ORDER BY
- 分頁LIMIT
- 23. 子查詢 和 嵌套查詢
- 五、MySQL函數
- 24. 常用函數(不常用)
- 25. 聚合函數(常用)
- 分組和過濾
- 26.拓展之 數據庫級別的MD5加密
- 1.MD5簡介
- 27. SELECT小結
- 內置函數小結:
- 六、事務
- 28.事務ACID原則、臟讀、不可重復讀、幻讀
附錄:
| DDL(數據定義語言) | 定義和管理數據對象,如數據庫、數據表等 | CREATE、DROP、ALTER |
| DML(數據操作語言) | 用于操作數據庫對象中所包含的數據 | INSERT、UPDATE、DALETE |
| DQL(數據查詢語言) | 用于查詢數據庫數據 | SELECT |
| DCL(數據控制語言) | 用于管理數據庫的語言,包括管理權限及數據更改 | GRANT、commit、rollback |
〇、視頻課鏈接
書:Mysql 必知必會
【狂神說Java】MySQL最新教程通俗易懂
【MySQL最新教程通俗易懂】 的 筆記:來自狂神說公眾號的文章—MySQL系列,和視頻課的內容稍有偏差,
還有另外一個筆記:MySQL基礎.md,這兩個筆記結合著看。
CSDN上的一個筆記:《數據庫系統概論》第五版 +學習筆記總目錄
還有Redis:【狂神說Java】Redis最新超詳細版教程通俗易懂
一、初識MySQL
1.為什么學習數據庫?
答:數據庫是幾乎軟件體系中最核心的一個存在。
2.什么是數據庫?
答:
概念 : 長期存放在計算機內,有組織,可共享的大量數據的集合,是一個數據 “倉庫”
作用 : 保存,并能安全管理數據(如:增刪改查等),減少冗余…
3.數據庫總覽(分類)☆☆☆
- 關系型數據庫(SQL)
MySQL,Oracle,SQL Server,DB2…
關系型數據庫通過外鍵關聯來建立表與表之間的關系。 - 非關系型數據庫(NOSQL)—Not Only SQL
Redis,MongoDB,…
非關系型數據庫通常指數據以對象的形式存儲在數據庫中,而對象之間的關系通過每個對象自身的屬性來決定。
4.什么是DBMS
答:
數據庫管理系統 ( DataBase Management System),
數據庫管理軟件 , 科學組織和存儲數據 , 高效地獲取和維護數據。
5.安裝MySQL
在Windows上安裝mysql5.7 64位 (百度云里有保存包裝包)
安裝步驟:
1、下載后得到zip壓縮包(用這個安裝比較干凈,哈哈,好像是說卸載的時候好卸載,能卸載干凈)
2、解壓到自己想要安裝到的目錄,本人解壓到的是D:\mysql-5.7.19-winx64\mysql-5.7.19-winx64
3、添加環境變量:我的電腦->屬性->高級->環境變量
選擇PATH,在其后面添加: 你的mysql 安裝文件下面的bin文件夾的路徑
4、編輯 my.ini 文件
在mysql 安裝文件下添加一個my.ini 文件(可以先新建一個txt文件,然后后綴改成.ini,再用記事本打開編輯),注意替換路徑位置
5、啟動管理員模式下的CMD,
并將路徑切換至**mysql下的bin目錄(D:\mysql-5.7.19-winx64\mysql-5.7.19-winx64\bin)**下,
然后輸入mysqld –install (安裝mysql)
6、再輸入 mysqld --initialize-insecure --user=mysql 初始化數據文件,初始化之后,在mysql安裝文件下會生成一個data文件夾:
7、然后再次啟動mysql ;
然后用命令 mysql –u root –p 進入mysql管理界面(密碼可為空)
8、進入界面后更改root密碼(用戶名是root,密碼改為123456)
update mysql.user set authentication_string=password('123456') where user='root' and Host = 'localhost';這里記得加最后面的英文分號。
修改完密碼之后,就進入mysql的狀態下了:
9、刷新權限
flush privileges;10、修改 my.ini文件刪除(注釋掉)最后一句skip-grant-tables
11、先退出mysql服務;
然后關閉重啟mysql即可正常使用;
12、最后再連接數據庫(命令行方式連接數據庫):
6.安裝可視化工具SQLyog
安裝包在百度云里:
安裝步驟:
剩下的都是傻瓜式安裝,注意修改下安裝路徑,我把它安裝在D盤:D:\SQLyog
安裝好之后新建一個連接:(可視化方式連接數據庫)
然后就可以進行可視化操作了。
7.用 SQLyog 創建數據庫 和 創建表
①創建數據庫school
這個操作對應的命令行指令是:
②創建表
這步操作對應的命令行指令巨長,所以說用可視化的軟件操作起來更方便,但一些基本的指令還是要會,不知道怎么寫就去歷史記錄查看每一步可視化操作對應的代碼。
③查看表(打開表)
④小結:
每一個SQLyog的執行操作,本質上就是對應了一個sql,可在歷史記錄中查看。
⑤注釋 + 運行單行代碼
注釋用兩個杠-- 注釋內容,注意--后面要加個空格,然后再寫注釋內容。(見下圖)
運行單行代碼:
8.用命令行連接數據庫
因為在上面的5.安裝MySQL中添加了環境變量,所以可以在任意目錄下連接數據庫。
- 在DOS命令行窗口輸入連接數據庫語句:
然后輸入密碼就可成功連接數據庫。
幾個基本的數據庫操作命令
//安裝mysql的時候的操作: update user set password=password('123456')where user='root'; 修改密碼 flush privileges; 刷新數據庫 //對數據庫的一些基本操作: show databases; 顯示所有數據庫 use school;打開數據庫school show tables; 顯示數據庫school中所有的表 describe student; 顯示表school數據庫中student表的列信息 describe teacher; 顯示表school數據庫中teacher表的列信息create database name; 創建數據庫exit; 退出Mysql ? 命令關鍵詞 : 尋求幫助 -- 表示注釋注意:
如果是在DOS命令窗口進行數據庫的操作,就要輸入如下指令,一定要全大寫字母,否則很多指令就是無效指令。
可以先在SQLyog中輸入上面的小寫形式的代碼,然后再在歷史記錄中把全大寫的寫法復制到DOS命令窗口中,因為SQLyog自動把所有小寫轉換成大寫。
(這里最好是直接復制過去,自己看著手寫一遍,但有的符號格式就是不對,直接復制就不會出錯,更保險)
9.數據庫的基本知識
數據庫類似于Excel表,一個數據庫類似于一個類class,
表的每一列,即列屬性,是類中的成員變量/成員屬性,數據庫中叫字段;
表的每一行,即行屬性,是類的一個具體的對象。
10.結構化查詢語句分類
| DDL(數據定義語言) | 定義和管理數據對象,如數據庫、數據表等 | CREATE、DROP、ALTER |
| DML(數據操作語言) | 用于操作數據庫對象中所包含的數據 | INSERT、UPDATE、DALETE |
| DQL(數據查詢語言) | 用于查詢數據庫數據 | SELECT |
| DCL(數據控制語言) | 用于管理數據庫的語言,包括管理權限及數據更改 | GRANT、commit、rollback |
二、操作數據庫和數據表(創建、刪除、使用、顯示、修改)
操作數據庫 --> 操作數據庫中的表 --> 操作數據庫中表的數據2.1 命令行操作數據庫(創建數據庫、刪除數據庫、使用數據庫、顯示數據庫)☆☆☆
(了解)
創建數據庫 : create database [if not exists] 數據庫名; 例如:CREATE DATABASE IF NOT EXISTS animals刪除數據庫 : drop database [if exists] 數據庫名; 例如:DROP DATABASE IF EXISTS animals顯示所有數據庫:show databases; 例如:SHOW DATABASES;-- 顯示所有數據庫使用數據庫:use 數據庫名; 例如:USE `school` -- 使用數據庫school 注意:如果表名或字段名是一個特殊字符,就需要帶 ``(tab鍵上面的)顯示數據庫school中所有的表:show tables; 顯示表school數據庫中student表的列信息:describe student; 顯示表school數據庫中teacher表的列信息:describe teacher;學習思路:
對照SQLyog可視化軟件的歷史記錄查看sql;
固定的語法或關鍵字必須要記住。
2.2 數據字段 的 類型 和 屬性(重要)
1.列名:
- 也叫列屬性,類似于類的成員屬性,也叫字段。
2.數據類型(重要):
①數值類型(int 和 decimal) 和 字符串(varchar):
數值:
int :整型數據
decimal:存儲金額(金額必須是精確值,而float和double都不能精確表示一個小數,decimal的底層是一個字符串,所以它能精確表示一個小數),
語法:DECIMAL(M,D)
其中,M是最大位數(精度),范圍是1到65。可不指定,默認值是10;D是小數點右邊的位數(小數位),范圍是0到30,并且不能大于M,可不指定,默認值是0。
例如:字段 salary DECIMAL(5,2),能夠存儲具有五位數字和兩位小數的任何值,因此可以存儲在salary列中的值的范圍是從-999.99到999.99。
示例:DECIMAL(10,2)表示數據最大長度為10,小數點后有兩位。
CREATE DATABASE `shop` CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE TABLE `account` (`id` INT(4) NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) NOT NULL,`money` DECIMAL(10,2) NOT NULL, -- VARCHAR(30)PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `account` VALUES(12,'小王',1000),(16,'小張',800)結果:
字符串:
varchar :存儲字符串
text:保存大文本
②日期和時間型數值類型(datetime) 和 NULL值:
datetime:YYYY-MM-DD HH:mm:ss
timestamp:時間戳
3.長度:
- 該數據的長度
4.默認:
- 用于設置默認值;
- 例如:性別字段,默認為"男" , 否則為 “女” ; 若無指定該列的值 , 則默認值為"男"的值
5.主鍵:
- 一個表中只能有一個主鍵。
6.非空(NOT NULL):
- 如果設置為NOT NULL , 則該列必須有值。
7.Unsigned:
- 無符號,表明該數據列不允許出現負數;
8.自增(Auto_InCrement):
- 自動增長的 , 每添加一條數據 , 默認是自動在上一個記錄數上加 1(默認);
- 通常用于設置主鍵 , 且為整數類型(int);
- 可以自定義自增量(高級—自動增量)
9.Zerofill:
- 用0填充,不足位數的用零來填充;
- 例如:int(3),輸入一個5,就會顯示005。
10.更新:
- 后面會講。
11.注釋:
- 給字段值/列名加個注釋。
2.3 每一個表都必須存在以下五個字段
以后會講,未來做項目用的,表示一個紀錄存在的意義。
2.4 創建數據表(CREATE TABLE)☆☆☆
2.4.1 看個例子
1.表名還有數據字段的屬性都用飄``括起來;
2.comment表示注釋,注釋內容用單引號’‘括起來;
3.default表示默認值,默認值也用單引號’'括起來;
4.PRIMARY KEY表示主鍵,一般把主鍵的設置放在最后,且主鍵只有一個;
5.ENGINE是引擎(具體見本節的2.4.3 補充),CHARSET是字符集。
注意:創建表之前 , 一定要先選擇數據庫,例如下面先選擇數據庫school,然后選中創建表的語句,然后點擊單句運行按鈕。
2.4.2 創建表的格式:
CREATE TABLE [IF NOT EXISTS] ``( `字段名` 列類型 [屬性] [索引] [注釋], `字段名` 列類型 [屬性] [索引] [注釋], ... `字段名` 列類型 [屬性] [索引] [注釋], PRIMARY KEY (`字段名`) )[表類型][字符集設置][注釋]如果上面的寫不出來,有個偷懶的操作,就是先用SQLyog進行可視化操作,然后再用下面的指令來查看具體的指令是怎么寫的,初學階段不推薦這樣做。
-- 查看創建數據庫school的語句 SHOW CREATE DATABASE school;-- 查看創建數據表student的語句 SHOW CREATE TABLE student;-- 顯示表結構 DESC student; 這個效果和前面說過的是一樣的: describe student; 顯示表school數據庫中student表的列信息 describe teacher; 顯示表school數據庫中teacher表的列信息2.4.3 補充:數據表的 引擎(類型) 和 字符集
創建表時寫了一個ENGINE = InnoDB,這個是數據表的引擎的意思,也就是數據表的類型的意思;還寫了個DEFAULT CHARSET=utf8,這個是數據表的字符集,在哪里設置這兩個參數呢?
一、首先說引擎
引擎表示數據表的類型,MySQL的數據表的類型 : MyISAM , InnoDB , HEAP , BOB , CSV等…
常見的 MyISAM 與 InnoDB 類型:
InnoDB 是默認使用;MyISAM 是早些年使用的。
| 事務支持 | 不支持 | 支持 |
| 數據行鎖定 | 不支持 | 支持 |
| 外鍵約束 | 不支持 | 支持 |
| 全文索引 | 支持 | 不支持 |
| 表空間的大小 | 較小 | 較大,約為2倍 |
常規使用操作:
- MYISAM:節約空間,速度較快;
- INNODB:安全性高,事物的處理,多表多用戶操作。
數據表的類型不同,對應的底層文件也不同。
數據表的存儲位置:
- MySQL數據表以文件方式存放在磁盤中,包括表文件 , 數據文件 , 以及數據庫的選項文件;
- 位置 : Mysql安裝目錄\data下(D:\mysql-5.7.19-winx64\mysql-5.7.19-winx64\data)存放數據表 。data目錄下的不同的文件夾名對應不同的數據庫 , 每個文件夾下的各個文件名對應不同的數據表。
- *.frm —表結構定義文件;
- *.MYD —數據文件(data);
- *.MYI —索引文件(index);
- InnoDB類型數據表只有一個 *.frm文件 , 以及上一級目錄的ibdata1文件;
- MyISAM類型數據表就包括上面三個文件 。
二、然后說設置數據庫表字符集編碼:
我們可為數據庫,數據表,數據列設定不同的字符集,有兩種設定方法。
方式1:
- 創建表時通過命令來設置 , 如 : CREATE TABLE 表名()CHARSET = utf8;
如果創建時不設置字符集的話,會使用mysql默認的字符集編碼(不支持中文);
方式2:
- 可以在MySQL數據庫配置文件 my.ini 中直接設定:character-set-server=utf8;
- 不推薦,因為如果別的電腦沒配置這個,你的程序就沒法運行;
2.5 修改表、刪除表
2.5.1 修改數據表(ALTER TABLE)☆☆☆
修改表名 :ALTER TABLE 舊表名 RENAME AS 新表名 例如:ALTER TABLE student RENAME AS students添加字段 : ALTER TABLE 表名 ADD 字段名 列屬性[屬性] 例如:ALTER TABLE teacher ADD `id` INT(5)修改字段 : ALTER TABLE 表名 MODIFY 字段名 列類型[屬性] ALTER TABLE 表名 CHANGE 舊字段名 新字段名 列屬性[屬性] 例如: ALTER TABLE teacher ADD `id` INT(5) ALTER TABLE teacher CHANGE `age` `age1` INT(3)刪除字段 : ALTER TABLE 表名 DROP 字段名解釋:
- MODIFY — 修改約束(修改某個字段的屬性,或者說修改某個列屬性),不能重命名;
- CHANGE — 重命名(修改某個字段名,或者說修改某個列名),重命名的同時后面要加上新字段名的屬性,即修改約束,所以CHANGE關鍵字可以實現重命名+修改約束。
注意:
一般不用這兩個關鍵詞來修改,都是直接在表里修改:
2.5.2 刪除數據表(DROP TABLE)☆☆☆
刪除表: DROP TABLE [IF EXISTS] 表名 例如: 現在數據庫school中創建了一個數據表animal: CREATE TABLE IF NOT EXISTS `animal`(`name` VARCHAR(20) NOT NULL DEFAULT 'null' COMMENT '動物名稱')ENGINE=INNODB DEFAULT CHARSET=utf8 然后刪除表: DROP TABLE IF EXISTS animal注意:
所有的創建和刪除操作盡量加上判斷(IF EXISTS),以免報錯。
三、MySQL數據管理
3.1 數據庫級別的外鍵(了解即可)
有兩種方式去使用外鍵:
注意:
以上的操作都是物理外鍵,數據庫級別的外鍵,我們不建議使用(避免數據庫過多造成困擾,這里了解即可)
最佳實踐:
- 數據庫就是單純的表,只用來存數據,只有行(數據)和列(字段);
- 我們想使用多張表的數據,想使用外鍵**(程序去實現)**。
3.2 DML語言(增、刪、改—重要!全部記住)☆☆☆
數據庫意義:數據存儲,數據管理
DML語言:數據庫操作語言
- 增:insert
- 刪:delete
- 改:update
3.3 添加 — INSERT INTO ☆☆☆
1. 插入操作的格式 和 注意事項
-- 插入一條數據: INSERT INTO `表名`(`字段1`,`字段2`) VALUES('值1','值2');-- 插入多條數據: INSERT INTO `表名`(`字段1`,`字段2`) VALUES('值1-1','值1-2'),('值2-1','值2-2'),('值3-1','值3-2');注意:
2. 先創建兩個表:
-- grade表 CREATE TABLE `grade` (`id` INT(30) NOT NULL AUTO_INCREMENT COMMENT '年級id',`name` VARCHAR(50) NOT NULL COMMENT '年級名稱',PRIMARY KEY (`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8-- student表 CREATE TABLE IF NOT EXISTS `student` (`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '學號',`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性別',`birthday` DATETIME NOT NULL COMMENT '出生日期',`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭地址',`email` VARCHAR(30) DEFAULT NULL COMMENT '郵箱',`id_grade` INT(30) NOT NULL COMMENT '年級id',PRIMARY KEY(`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf83. 對表grade進行插入操作:
(插入一條數據)
-- 標準的插入語句:INSERT INTO `表名`(`字段1`,`字段2`) VALUES('值1','值2'); INSERT INTO `grade`(`id`,`name`) VALUES('123','大一'); -- 因為`id`字段是自增加,所以可以省略,只插入`name`字段的值 INSERT INTO `grade`(`name`) VALUES('大二');結果:
(插入多條數據)
結果:
注意:有默認值的字段可以不用賦值,但沒有默認值的數據必須賦值!!!
4. 對表student進行插入操作:
(插入一條、多條數據)
-- 標準的插入語句:INSERT INTO `表名`(`字段1`,`字段2`) VALUES('值1','值2'); -- 注意:插入一條數據,有默認值的字段可以不用賦值,但沒有默認值的必須要賦值 INSERT INTO `student`(`name`,`birthday`,`id_grade`) VALUES('aaa','1998-02-06 12:26:05','2017'); -- 插入多條數據: INSERT INTO `student`(`name`,`birthday`,`id_grade`) VALUES('abc','1996-05-09 12:26:05','2021'),('bbb','1995-02-28 12:26:05','2020'),('ccc','1994-12-20 12:26:05','2019'); INSERT INTO `student`(`id`,`name`,`sex`,`birthday`,`address`,`email`,`id_grade`) VALUES('121','樂樂','男','1995-02-28 16:20:00','西北大學','17966@qq.com','2020'); -- 如果不寫字段值,就要把給所有字段賦值: INSERT INTO `student` VALUES('156','萌萌','女','1994-12-20 16:20:00','西北大學','82628@qq.com','2017');結果:
3.4 修改 — UPDATE ☆☆☆
語法:
UPDATE `表名` SET `字段1/列屬性1`=value1,`字段2/列屬性2`=value2,... WHERE condition;例如:UPDATE student SET name = ‘xyz’會把該表中每條數據的name列屬性都修改成’xyz’
示例:
-- 修改一個字段值: -- 把(`id`字段值等于2的)數據的`name`字段內容改為'xyz' UPDATE `student` SET `name` = 'xyz' WHERE `id` = 2;-- 修改多個字段值: -- 把(`name`字段值等于'ccc'的)數據的`name`字段內容改為'ttt',`address`的字段內容'大雁塔' UPDATE `student` SET `name`='ttt',`address`='大雁塔' WHERE `name`='ccc';-- 注意:如果不加where條件,就會把該表中每條數據的列屬性都修改了,這是很危險的! -- 例如:UPDATE `student` SET `name` = 'xyz'會把該表中每條數據的`name`列屬性都修改成'xyz'-- 修改多個字段值,并且有多個篩選條件: UPDATE `student` SET `name`='畢業生',`address`='西北大學(已畢業)' WHERE `address`='西北大學' AND `id_grade`<='2017'結果:
補充:where后面的篩選條件
| = | 等于 | 5=6 | false |
| != 或 <> | 不等于 | 5<>6 | true |
| > | |||
| < | |||
| >= | |||
| <= | |||
| BETWEEN … AND … | 在某個范圍內 | [2,5] | |
| AND 或 && | 與 | 5>1 AND 1>2 | false |
| OR或 兩個豎杠 (避免使用這個) | 或 | 5>1 AND 1>2 | true |
3.5 刪除 — DELETE FROM ☆☆☆
語法:
DELETE FROM `表名` WHERE condition;condition依然是篩選條件;
注意:如果不指定篩選條件,則會刪除該表的所有列數據,這他媽就是刪庫跑路啊,一定注意,別這么干!!!
示例:
-- 直接清空整個數據表student: DELETE FROM `student`-- 把student表中`id_grade`字段值大于2020的數據刪除: DELETE FROM `student` WHERE `id_grade`>'2020'清空數據庫表 :TRUNCATE命令
作用:用于完全清空表數據 , 但表結構 , 索引 , 約束等不變 ;
語法:
TRUNCATE [TABLE] table_name;示例:
-- 清空年級表(兩種寫法都可以) TRUNCATE `grade` TRUNCATE TABLE `test`DELETE FROM 和 TRUNCATE 的區別
相同點:都能刪除數據,且都不會改變表的結構、索引、約束等。
不同點:
- truncate會重置自增列,計數器會歸零,但delete不會將計數器歸零;
- truncate不會影響事務(后面會講事務)
示例:
-- 創建一個測試表 CREATE TABLE `test` ( `id` INT(4) NOT NULL AUTO_INCREMENT, `coll` VARCHAR(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8-- 插入幾個測試數據 INSERT INTO test(coll) VALUES('row1'),('row2'),('row3');-- 刪除表數據(不帶where條件的delete) DELETE FROM test; -- 結論:如不指定Where則刪除該表的所有列數據,自增當前值依然從原來基礎上進行,會記錄日志.-- 刪除表數據(truncate) TRUNCATE TABLE test; -- 結論:truncate刪除數據,自增當前值會恢復到初始值重新開始;不會記錄日志.補充:(了解即可)delete 刪除的問題
使用DELETE清空不同引擎的數據庫表數據,重啟數據庫服務后
- InnoDB : 自增列從初始值重新開始 (因為是存儲在內存中,斷電即失)
- MyISAM : 自增列依然從上一個自增數據基礎上開始 (存在文件中,不會丟失)
四、DQL查詢數據(最重點!!!)
DQL(Database Query Language 數據查詢語言)
關鍵詞:SELETE
數據庫中最核心的語言,最重要的語句!!!
SELECT語法 --> 27.SELECT小結
SELECT [ALL | DISTINCT] {* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]} FROM table_name [as table_alias][left | right | inner join table_name2] -- 聯合查詢[WHERE ...] -- 指定結果需滿足的條件[GROUP BY ...] -- 指定結果按照哪幾個字段來分組[HAVING] -- 過濾分組的記錄必須滿足的次要條件[ORDER BY ...] -- 指定查詢記錄按一個或多個條件排序[LIMIT {[offset,]row_count | row_countOFFSET offset}];-- 指定查詢的記錄從哪條至哪條注意 :
- ①[ ] 括號代表可選的 , { }括號代表必選的;
- ②上面的各個可選部分是有順序的,不能打亂順序:
小目錄:
- 16 &17:SELECT [去重-DISTINCT] 要查詢的字段 FROM 數據表A (表和字段可用AS取別名)
- 20:xxx(INNER) JOIN 要連接的表B ON 交叉條件 – 連接查詢
- 18 & 19 & 23:WHERE 條件 – 篩選條件(如果有多個篩選條件,就在后面加AND關鍵字,不要加逗號,)模糊查詢(關鍵字LIKE和關鍵字IN)> 或者子查詢語句)
- 25:[GROUP BY …] – 通過哪個字段來分組
- 25:[HAVING] – 過濾分組后的信息,條件和where是一樣的,區別就是先后位置不同
- 22:ORDER BY – (通過哪個字段排序)[升序ASC / 降序DESC]
- 22:LIMIT startIndex, pageSize – 分頁
上面的可選部分順序很重要;
HAVING 和 WHERE的區別就在于先后位置不同。
預備工作:16-20的數據庫代碼:
-- 第一部分: CREATE DATABASE IF NOT EXISTS `school`; -- 創建一個school數據庫 USE `school`;-- 創建學生表 DROP TABLE IF EXISTS `student`; CREATE TABLE `student`(`studentno` INT(4) NOT NULL COMMENT '學號',`loginpwd` VARCHAR(20) DEFAULT NULL,`studentname` VARCHAR(20) DEFAULT NULL COMMENT '學生姓名',`sex` TINYINT(1) DEFAULT NULL COMMENT '性別,0或1',`gradeid` INT(11) DEFAULT NULL COMMENT '年級編號',`phone` VARCHAR(50) NOT NULL COMMENT '聯系電話,允許為空',`address` VARCHAR(255) NOT NULL COMMENT '地址,允許為空',`borndate` DATETIME DEFAULT NULL COMMENT '出生時間',`email` VARCHAR (50) NOT NULL COMMENT '郵箱賬號允許為空',`identitycard` VARCHAR(18) DEFAULT NULL COMMENT '身份證號',PRIMARY KEY (`studentno`),UNIQUE KEY `identitycard`(`identitycard`),KEY `email` (`email`) )ENGINE=MYISAM DEFAULT CHARSET=utf8;-- 第二部分: -- 創建年級表 DROP TABLE IF EXISTS `grade`; CREATE TABLE `grade`(`gradeid` INT(11) NOT NULL AUTO_INCREMENT COMMENT '年級編號',`gradename` VARCHAR(50) NOT NULL COMMENT '年級名稱',PRIMARY KEY (`gradeid`) ) ENGINE=INNODB AUTO_INCREMENT = 6 DEFAULT CHARSET = utf8;-- 創建科目表 DROP TABLE IF EXISTS `subject`; CREATE TABLE `subject`(`subjectno`INT(11) NOT NULL AUTO_INCREMENT COMMENT '課程編號',`subjectname` VARCHAR(50) DEFAULT NULL COMMENT '課程名稱',`classhour` INT(4) DEFAULT NULL COMMENT '學時',`gradeid` INT(4) DEFAULT NULL COMMENT '年級編號',PRIMARY KEY (`subjectno`) )ENGINE = INNODB AUTO_INCREMENT = 19 DEFAULT CHARSET = utf8;-- 創建成績表 DROP TABLE IF EXISTS `result`; CREATE TABLE `result`(`studentno` INT(4) NOT NULL COMMENT '學號',`subjectno` INT(4) NOT NULL COMMENT '課程編號',`examdate` DATETIME NOT NULL COMMENT '考試日期',`studentresult` INT (4) NOT NULL COMMENT '考試成績',KEY `subjectno` (`subjectno`) )ENGINE = INNODB DEFAULT CHARSET = utf8;-- 第三部分: -- 插入學生數據 其余自行添加 這里只添加了2行 INSERT INTO `student` (`studentno`,`loginpwd`,`studentname`,`sex`,`gradeid`,`phone`,`address`,`borndate`,`email`,`identitycard`) VALUES (1000,'123456','張偉',0,2,'13800001234','北京朝陽','1980-1-1','text123@qq.com','123456198001011234'), (1001,'123456','趙強',1,3,'13800002222','廣東深圳','1990-1-1','text111@qq.com','123456199001011233');-- 插入成績數據 這里僅插入了一組,其余自行添加 INSERT INTO `result`(`studentno`,`subjectno`,`examdate`,`studentresult`) VALUES (1000,1,'2013-11-11 16:00:00',85), (1000,2,'2013-11-12 16:00:00',70), (1000,3,'2013-11-11 09:00:00',68), (1000,4,'2013-11-13 16:00:00',98), (1000,5,'2013-11-14 16:00:00',58);-- 插入年級數據 INSERT INTO `grade` (`gradeid`,`gradename`) VALUES(1,'大一'),(2,'大二'),(3,'大三'),(4,'大四'),(5,'預科班');-- 第四部分: -- 插入科目數據 INSERT INTO `subject`(`subjectno`,`subjectname`,`classhour`,`gradeid`) VALUES (1,'高等數學-1',110,1), (2,'高等數學-2',110,2), (3,'高等數學-3',100,3), (4,'高等數學-4',130,4), (5,'C語言-1',110,1), (6,'C語言-2',110,2), (7,'C語言-3',100,3), (8,'C語言-4',130,4), (9,'Java程序設計-1',110,1), (10,'Java程序設計-2',110,2), (11,'Java程序設計-3',100,3), (12,'Java程序設計-4',130,4), (13,'數據庫結構-1',110,1), (14,'數據庫結構-2',110,2), (15,'數據庫結構-3',100,3), (16,'數據庫結構-4',130,4), (17,'C#基礎',130,1);UPDATE student SET `studentname`='張強強' WHERE `studentno`=1001 UPDATE student SET `studentname`='張偉強' WHERE `studentno`=1000INSERT INTO `student` (`studentno`,`loginpwd`,`studentname`,`sex`,`gradeid`,`phone`,`address`,`borndate`,`email`,`identitycard`) VALUES (1002,'123456','劉杰',0,2,'1381234','','1986-1-1','tex3@qq.com','123001011234'), (1003,'123456','樂樂',0,2,'1380001234','','','','')UPDATE student SET `address`=NULL WHERE `studentname`='樂樂'16. 查詢某個字段select 和 給字段起別名as
1.查詢某個數據表的所有字段/某些指定字段:關鍵字SELECT
2.給某個字段或者數據表起別名:關鍵字AS
示例:
-- ①查詢某個數據表的所有字段(用*作為通配符) SELECT * FROM `student`-- ②查詢某個數據表的指定字段 SELECT `studentno`,`studentname` FROM `student`-- ③給字段或數據表加個別名 -- 注意:數據表的別名不要加單引號:SELECT `studentno` as '學號',`studentname` as '姓名' FROM `student` as '表1' -- 下面兩種寫法都可以: SELECT `studentno` AS '學號',`studentname` AS '姓名' FROM `student` AS 表1 SELECT `studentno` AS 學號,`studentname` AS 姓名 FROM `student` AS 表1-- ④調用函數CONCAT()來拼接字符串: SELECT CONCAT('學號:',`studentno`) ,CONCAT('姓名:',`studentname`) FROM `student`⑤調用函數CONCAT()來拼接字符串 + 重命名字段: SELECT CONCAT('學號:',`studentno`) AS 學號信息,CONCAT('姓名:',`studentname`) AS 姓名信息 FROM `student`結果:
①查詢某個數據表的所有字段(用*作為通配符)
②查詢某個數據表的指定字段
③給字段或數據表加個別名
④調用函數CONCAT()來拼接字符串:
⑤調用函數CONCAT()來拼接字符串 + 重命名字段
17. 去重復distinct 及 數據庫中的表達式
作用 : 去掉SELECT查詢返回的記錄結果中重復的記錄 ( 返回所有列的值都相同 ) , 只返回一條。
示例:通過(學號) 字段查看哪些同學參加了考試并去除重復項
-- ①先查看存儲考試成績的數據表result:(查看所有字段) SELECT * FROM result;-- ②查看哪些同學參加了考試:(查看學號studentno字段) SELECT studentno FROM result; -- ②用 DISTINCT 去除重復項: SELECT DISTINCT studentno FROM result;結果:
①
②
③
數據庫中的表達式:
一般由文本值 , 列值 , NULL , 函數和操作符等組成。
①
②
③
④
⑤
18. where子句之邏輯運算符
作用:查詢時的篩選條件。
邏輯操作符:
| AND 或 && | a AND b 或 a && b | 邏輯與 |
| OR 或 兩個豎杠 | a OR b 或 a 兩個豎杠 b | 邏輯或 |
| NOT 或 ! | NOT a 或 !a | 邏輯非 |
示例:
-- 滿足條件的查詢(where) SELECT Studentno,StudentResult FROM result;-- 查詢考試成績在95-100之間的 SELECT Studentno,StudentResult FROM result WHERE StudentResult>=95 AND StudentResult<=100;-- AND也可以寫成 && SELECT Studentno,StudentResult FROM result WHERE StudentResult>=95 && StudentResult<=100;-- 模糊查詢(對應的詞:精確查詢) SELECT Studentno,StudentResult FROM result WHERE StudentResult BETWEEN 95 AND 100;-- 除了1000號同學,要其他同學的成績 SELECT studentno,studentresult FROM result WHERE studentno!=1000;-- 使用NOT SELECT studentno,studentresult FROM result WHERE NOT studentno=1000;19. 模糊查詢操作符☆☆☆
比較操作符:
| IS NULL 或 =‘’ | a IS NULL | 若a為空,結果為真 |
| IS NOT NULL | a IS NOT NULL | 若a為非空,結果為真 |
| BETWEEN | a BETWEEN b AND c | 若a在區間[b,c]內,結果為真 |
| LIKE(重要) | a LIKE b | SQL模式匹配:若a匹配b,則結果為真 |
| IN(重要) | a IN (a1, a2, a3, …) | 若a為(a1, a2, a3, …)中的某一個,結果為真 |
補充:
關鍵字LIKE結合使用的通配符 :
- % (代表0到任意個字符) ;
- _ (表示一個字符);
- __ (表示兩個字符)。
關鍵詞IN
注意:
- 數值數據類型的記錄之間才能進行算術運算 ;
- 相同數據類型的數據之間才能進行比較 ;
示例:
-- 模糊查詢 between and \ like \ in \ null-- ============================================= -- LIKE -- ============================================= -- 查詢姓張的同學的學號及姓名 -- like結合使用的通配符 : % (代表0到任意個字符) _ (一個字符) SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '張%'-- 查詢姓張的同學,后面只有一個字的 SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '張_'-- 查詢姓張的同學,后面只有兩個字的 SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '張__'-- 查詢姓名中含有 偉 字的 SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '%偉%'-- 查詢姓名中含有 強 字的 SELECT `studentno`,`studentname` FROM student WHERE `studentname` LIKE '%強%'-- 查詢姓名中含有特殊字符的需要使用轉義符號 '\' -- 自定義轉義符關鍵字: ESCAPE ':'-- ============================================= -- IN -- ============================================= -- 查詢學號為1000,1001,1002的學生姓名 SELECT `studentno`,`studentname` FROM student WHERE `studentno` IN (1000,1001,1002) -- -- 查詢地址在'北京','北京朝陽','南京','廣東深圳'的學生 SELECT `studentno`,`studentname` FROM student WHERE `address` IN ('北京','北京朝陽','南京','廣東深圳')-- ============================================= -- NULL 空 -- ============================================= -- 查詢出生日期沒有填寫的同學 -- 不能直接寫=NULL , 這是代表錯誤的 , 用 is null SELECT studentname FROM student WHERE BornDate IS NULL;-- 查詢出生日期填寫的同學 SELECT `studentno`,`studentname` FROM student WHERE `borndate` IS NOT NULL-- 查詢沒有寫家庭住址的同學(空字符串不等于null) SELECT * FROM student SELECT `studentno`,`studentname` FROM student WHERE `address`='' -- 結果有兩條 SELECT `studentno`,`studentname` FROM student WHERE`address` IS NULL -- 結果是空注意:
IS NULL這塊,空字符串并不等于NULL;
判斷是否是空字符串,要用=''
結果:
20. 聯表查詢
連接查詢 join on
等值查詢 where
連接查詢:
如需要多張數據表的數據進行查詢,則可通過連接運算符實現多個查詢。
| INNER JOIN | 如果表中至少有一個匹配,則返回行 |
| LEFT JOIN | 以左表作為基準,即使右表中沒有匹配,也從左表中返回所有的行 |
| RIGHT JOIN | 以右表作為基準,即使左表中沒有匹配,也從右表中返回所有的行 |
七種Join對比:
連接查詢的思路:
1.分析需求,分析查詢的字段來自哪些表;(連接查詢)
2.確定使用哪種連接查詢(7種);
3.確定交叉點(兩個表中哪個數據是相同的);
4.判斷的條件:數據表A的cc字段 = 數據表B的cc字段
示例:(注意區分等值查詢和連接查詢的寫法)
-- 查詢參加了考試的同學信息(學號,學生姓名,科目編號,分數) SELECT * FROM student; SELECT * FROM result;/*思路: (1)分析需求,確定查詢的列來源于兩個表,student result,連接查詢 (2)確定使用哪種連接查詢?(內連接inner join) (3)交叉點:兩個表都有 studentno 字段 (4)判斷的條件:r.studentno = s.studentno */ SELECT s.`studentno`,`studentname`,`subjectno`,`studentresult` FROM student s INNER JOIN result r ON r.studentno = s.studentno -- 上面的s.`studentno`也可以寫成s.studentno-- 右連接(也可實現) SELECT s.`studentno`,`studentname`,`subjectno`,`studentresult` FROM student s RIGHT JOIN result r ON r.studentno = s.studentno-- 左連接 (查詢了所有同學,不考試的也會查出來) SELECT s.`studentno`,`studentname`,`subjectno`,`studentresult` FROM student s LEFT JOIN result r ON r.studentno = s.studentno-- 等值連接 SELECT s.studentno,studentname,subjectno,StudentResult FROM student s , result r WHERE r.studentno = s.studentno-- 查一下缺考的同學(左連接應用場景)以左表為基準,即student 表中有的,即使右表(result)中沒有,也要輸出; SELECT s.studentno,studentname,subjectno,StudentResult FROM student s LEFT JOIN result r ON r.studentno = s.studentno WHERE StudentResult IS NULL -- 最后再加一個條件:學生成績為空,這是在右表中沒有的-- 思考題:查詢參加了考試的同學信息(學號,學生姓名,科目名,分數) /*思路: (1)分析需求,確定查詢的列來源于三個表,student result subject,連接查詢 (2)確定使用哪種連接查詢?(內連接inner join) (3)交叉點:這幾個表兩兩之間的共有字段是什么? (4)判斷的條件:r.studentno = s.studentno */ SELECT s.studentno,studentname,subjectname,StudentResult FROM student s INNER JOIN result r ON r.studentno = s.studentno -- 以上找到表student和表result共有的部分 INNER JOIN `subject` sub ON sub.subjectno = r.subjectno -- 再將表student和標result共有的部分 和 表subject進行連接查詢,找到共有的部分總結:
1.假如要查詢的字段是兩個表共有的,那么就要給兩個表起個別名,然后用一個表的別名.公有字段,例如下面的**s.studentno** ,兩個表都有studentno字段,SELECT 后就要寫成s.studentno或者r.studentno,否則會提示ambiguous(模棱兩可);
2.假設存在多張表查詢,慢慢來,先查詢兩張表,再慢慢往后查(類似上面示例中最后的思考題)。
– INNER JOIN的格式和例子:
SELECT 要查詢的字段們 FROM 表A 表A的別名 INNER JOIN 表B 表B的別名 ON 交叉條件SELECT s.`studentno`,`studentname`,`subjectno`,`studentresult` FROM student s INNER JOIN result r ON r.studentno = s.studentno– 等值連接的格式和例子:
SELECT 要查詢的字段們 FROM 表A 表A的別名, 表B 表B的別名 WHERE 交叉條件SELECT s.studentno,studentname,subjectno,StudentResult FROM student s , result r WHERE r.studentno = s.studentno練習題:
-- 查詢學員所屬的年級(學號、學生姓名、年級名稱) SELECT `studentno`,`studentname`,`gradename` FROM `student` s INNER JOIN `grade` g ON s.`gradeid` = g.`gradeid`-- 查詢科目所屬的年級(科目名稱、年級名稱) SELECT `gradename`,`subjectname` FROM `grade` g INNER JOIN `subject` s ON g.`gradeid` = s.`gradeid`-- 查詢參加 高等數學-2 考試的同學信息:學號,學生姓名、科目名、分數 SELECT s.`studentno`,`studentname`,`subjectname`,`studentresult` FROM `student` s INNER JOIN `subject` sub ON s.`gradeid` = sub.`gradeid` INNER JOIN `result` r ON sub.`subjectno` = r.`subjectno` WHERE `subjectname` = '高等數學-2' -- 最后再加一個判斷條件:科目名稱為 '高等數學-2'21. 自連接
自連接:自己的表和自己的表連接,核心是一張表拆為兩張一樣的表,父類和子類。
-- 創建表 -- unsigned 無符號 -- auto_increment=9 自增的起始值 DROP TABLE IF EXISTS `category` ; CREATE TABLE `category` (`category_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主題id',`pid` INT(10) NOT NULL COMMENT '父id',`category_name` VARCHAR(50) NOT NULL COMMENT '主題名字',PRIMARY KEY (`category_id`) ) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;-- 插入值 INSERT INTO `category`(`category_id`,`pid`,`category_name`) VALUES('2','1','信息技術'), ('3','1','軟件開發'), ('4','3','數據庫'), ('5','1','美術設計'), ('6','3','web開發'), ('7','5','ps技術'), ('8','2','辦公信息');SELECT * FROM `category`;創建的表如下:
將原來的表分成兩個一樣的表:
父類:
子類:
操作:查詢父類對應的子類關系(父類的categoryid 等于 子類的pid)
等值查詢
-- 查詢父子信息,把一張表看為兩個一模一樣的表 SELECT a.`category_name` AS '父欄目',b.`category_name` AS '子欄目' FROM `category` AS a, `category` AS b WHERE a.`category_id`=b.`pid`;結果:
22. 分頁limit 和 排序order by
排序 ORDER BY
排序:一般是先查詢,然后再排序。
排序的語法:
其中,排序規則有升序和降序兩種,升序是ASC,降序是DESC。
示例:上面練習題的最后一題:(查詢參加 高等數學-2 考試的同學信息:學號,學生姓名、科目名、分數)
升序:
降序:
分頁LIMIT
為什么要分頁?
假如數據有100w條,就有必要分頁,除了緩解數據庫壓力,還可以給人更好的體驗。當然也有不分頁的,叫做瀑布流,比如抖音、百度上的圖片,一直往下拉刷不完。
現在對一組數據分頁,每頁只顯示五條數據:
-- 分頁的語法: LIMIT 起始值,頁面的大小LIMIT 0,5 -- 1~5 從第1條數據開始(下標為0),顯示第1-5條信息 LIMIT 1,5 -- 2~6 從第2條數據開始(下標為0),顯示第2-6條信息 LIMIT 5,5 -- 6-10 從第6條數據開始(下標為0),顯示第6-10條信息分頁涉及到的概念:當前頁、總頁數,每頁的大小pageSize
推導一下:
– 第一頁 LIMIT 0,5 (1-1)*5
– 第二頁 LIMIT 5,5 (2-1)*5
– 第三頁 LIMIT 10,5 (3-1)*5
– 第N頁 LIMIT 10,5 (n-1)*pageSize,pageSize
pageSize表示頁面大小;(n-1)*pageSize表示起始值;n表示當前頁;總頁數 = (數據總數%頁面大小==0)? (數據總數/頁面大小) : (數據總數/頁面大小 + 1)。
示例:
** 上面練習題的最后一題:(查詢參加 高等數學-2 考試的同學信息:學號,學生姓名、科目名、分數) SELECT s.`studentno`,`studentname`,`subjectname`,`studentresult` FROM `student` s INNER JOIN `subject` sub ON s.`gradeid` = sub.`gradeid` INNER JOIN `result` r ON sub.`subjectno` = r.`subjectno` WHERE `subjectname` = '高等數學-2' -- 最后再加一個判斷條件:科目名稱為 '高等數學-2' ORDER BY `student_result` DESC -- 降序排序 LIMIT 0,5; -- 分頁,每頁顯示五條信息,思考題:
-- 思考題: -- 查詢科目高等數學-2,課程成績排名前十的學生,并且分數要大于60的學生信息(學號,姓名,課程名稱,分數) SELECT s.`studentno`,`studentname`,`subjectname`,`studentresult` -- 這樣寫也可以: SELECT s.`student_no`,s.`student_name`,sub.`subject_name`,res.`student_result` FROM `student` s INNER JOIN `subject` sub ON sub.`gradeid` = s.`gradeid` INNER JOIN `result` r ON r.`studentno` = s.`studentno` -- where條件: WHERE `subjectname` = '高等數學-2' AND `studentresult` > 60 -- 排序: ORDER BY `studentresult` DESC -- 這樣寫也可以: ORDER BY res.`student_result` -- 分頁:因為是前10名,所以就把每頁的大小設置為10,這樣就可以顯示出前10名 LIMIT 0,10 -- 這樣寫也可以: LIMIT 0,10; -- 語法: limit (查詢起始下標,頁面大小)如果有多個篩選條件,就在WHERE后面加個AND,不要用逗號,
23. 子查詢 和 嵌套查詢
之前用where的時候,后面是一個確定的值或者范圍,例如上面的思考題中的
-- where條件: WHERE `subjectname` = '高等數學-2' AND `studentresult` > 60其實,在where后面還可以跟一個子查詢語句,這就是子查詢。
子查詢的本質就是在where語句中嵌套一個子查詢語句;
嵌套查詢可由多個子查詢組成,求解的方式是由里及外;
子查詢返回的結果一般都是集合,故而建議使用IN關鍵字。
說到底,
子查詢和嵌套查詢就是不用像連接查詢那樣連接多個表,
而是把某個表的查詢工作放到一個WHERE條件中(示例1的方法二和示例2的方法二),
或者把所個表的查詢工作放到一個IN中(示例2的方法三)。
示例1:
-- 查詢 '高等數學-2' 的所有考試結果(學號,科目編號,成績),并且成績降序排列 -- 方法一:使用連接查詢 SELECT r.`studentno`,r.`subjectno`,r.`studentresult` FROM `result` r INNER JOIN `subject` sub ON sub.`subjectno` = r.`subjectno` WHERE `subjectname` = '高等數學-2' ORDER BY `studentresult` DESC-- 方法二:使用子查詢(一層嵌套) SELECT `studentno`,`subjectno`,`studentresult` FROM `result` WHERE `subjectno` = (SELECT `subjectno` FROM `subject`WHERE `subjectname` = '高等數學-2' ) ORDER BY `studentresult` DESC結果:
示例2:
結果:
練習題目:
查 C語言-1 的前5名學生的成績信息(學號,姓名,分數)
總結:
方式一就是直接把所有表全連接到一起,比較簡單,但要注意避免出現ambiguous,即必須明確要查詢的字段確保不出現歧義;
方式二就是把個別表的查詢放入where中,相對更適合自己;
方式三的話感覺要求更高,像上面的練習題,要查詢來自兩個表的三個字段,用方式三好像實現不了(不確定,可能是自己太菜)。
五、MySQL函數
24. 常用函數(不常用)
MySQL 2.7 參考手冊:點這里,官方手冊,可以翻譯成中文。
數據函數:
SELECT ABS(-8); /*絕對值*/SELECT CEILING(9.4); /*向上取整*/SELECT FLOOR(9.4); /*向下取整*/SELECT RAND(); /*隨機數,返回一個0-1之間的隨機數*/SELECT SIGN(0); /*符號函數: 負數返回-1,正數返回1,0返回0*/字符串函數:
SELECT CHAR_LENGTH('狂神說堅持就能成功'); /*返回字符串包含的字符數*/SELECT CONCAT('我','愛','程序'); /*合并字符串,參數可以有多個*/SELECT INSERT('我愛編程helloworld',1,2,'超級熱愛'); /*替換字符串,從某個位置開始替換某個長度*/SELECT LOWER('KuangShen'); /*小寫*/SELECT UPPER('KuangShen'); /*大寫*/SELECT LEFT('hello,world',5); /*從左邊截取*/SELECT RIGHT('hello,world',5); /*從右邊截取*/SELECT REPLACE('狂神說堅持就能成功','堅持','努力'); /*替換字符串*/SELECT SUBSTR('狂神說堅持就能成功',4,6); /*截取字符串,開始和長度*/SELECT REVERSE('狂神說堅持就能成功'); /*反轉-- 查詢帶 偉 的同學,改成 尾 SELECT REPLACE(`studentname`,'偉','尾') AS '新名字' FROM `student` WHERE `studentname` LIKE '%偉%'日期和時間函數:
SELECT CURRENT_DATE(); /*獲取當前日期*/SELECT CURDATE(); /*獲取當前日期*/SELECT NOW(); /*獲取當前日期和時間*/SELECT LOCALTIME(); /*獲取當前日期和時間*/SELECT SYSDATE(); /*獲取當前日期和時間*/-- 獲取年月日,時分秒SELECT YEAR(NOW());SELECT MONTH(NOW());SELECT DAY(NOW());SELECT HOUR(NOW());SELECT MINUTE(NOW());SELECT SECOND(NOW());系統信息函數:
SELECT VERSION(); /*版本*/SELECT USER(); /*用戶*/25. 聚合函數(常用)
MySQL 2.7 參考手冊:點這里,官方手冊,可以翻譯成中文。
| COUNT() | 計數,如 select count(*) 【不建議使用 *,效率低】 |
| SUM() | 求和 |
| AVG() | 平均值 |
| MAX() | 最大值 |
| MIN() | 最小值 |
COUNT()函數有以下幾種用法:
SELECT COUNT(`studentname`) FROM `student` -- 4 SELECT COUNT(`email`) FROM `student` -- 4 SELECT COUNT(*) FROM `student` -- 4 SELECT COUNT(1) FROM `student` -- 4- count(字段) 統計該字段在表中出現的次數,不會統計字段為null 的記錄;
- count(*) 會統計字段為null 的記錄;
- count(1) 會統計字段為null 的記錄 ;
- 從含義上講,count(1) 與 count(*) 都表示對全部數據行的查詢。
下面它們之間的一些對比:
1)在表沒有主鍵時,count(1)比count(*)快
2)有主鍵時,主鍵作為計算條件,count(主鍵)效率最高;
3)若表格只有一個字段,則count(*)效率較高。
其他幾個函數:
計算 result表 中的 studentresult字段 的總和、平均分、最高分、最低分:
分組和過濾
上面知道怎么怎么求 result表 中的 studentresult字段 的平均分、最高分、最低分,但這是所有科目的成績加在一起之后算出來的,現在要求各個科目的平均分、最高分、最低分,就要用到分組和過濾了。
-- 查詢不同課程的平均分,最高分,最低分-- 前提:根據不同的課程進行分組 SELECT `subjectname` AS '課程名稱', SUM(`studentresult`) AS '總分', AVG(`studentresult`) AS '平均分', MAX(`studentresult`) AS '最高分', MIN(`studentresult`) AS '最低分' FROM `result` r INNER JOIN `subject` sub ON sub.`subjectno` = r.`subjectno` -- GROUP BY r.`subjectno` -- 通過課程編號來分組 GROUP BY `subjectname` -- 通過課程名稱來分組 -- HAVING AVG(`studentresult`) > 50 -- 這樣寫不會出錯 HAVING 平均分 > 50 -- 也可以這樣寫,但下面的方式就不行 -- HAVING '平均分' > 50 -- 不知道為什么加了單引號結果就不對,所以最保險的就是用第一種方式寫分組和篩選的格式:
WHERE 字段 -- 指定結果需滿足的條件 GROUP BY 字段 -- 指定結果按照哪幾個字段來分組 HAVING 次要篩選條件 -- 過濾分組的記錄必須滿足的次要條件
注意:
1.篩選條件where必須寫在group by前面;
2.要是在分組后面還要加篩選條件,就要使用HAVING…
因為having是從前面篩選的字段再篩選,而where是從數據表中的字段直接進行的篩選的。
26.拓展之 數據庫級別的MD5加密
1.MD5簡介
什么是MD5?
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致,是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5的前身有MD2、MD3和MD4。
MD5的作用:主要增加算法復雜度和不可逆性。
MD5的特點:MD5不可逆,具體的值的md5是一樣的。
補充:MD5破解網站的原理,背后有一個字典,字典里是經MD5加密后的值,將用戶傳遞進來的密碼,進行MD5加密,然后比對加密后的值,如果在字典里找到了,就返回加密前的值。
示例:
-- 創建表: CREATE TABLE `testmd5`(`id` INT(4) NOT NULL,`name` VARCHAR(20) NOT NULL,`pwd` VARCHAR(50) NOT NULL,PRIMARY KEY(`id`) )ENGINE = INNODB DEFAULT CHARSET=utf8-- 插入數據: INSERT INTO `testmd5`(`id`,`name`,`pwd`) VALUES (1,'小王','123456'), (2,'小張','123456'), (3,'小劉','123456'), (5,'小趙','123456')SELECT * FROM `testmd5`-- 給單條數據(`id` = 1)加密: UPDATE `testmd5` SET `pwd`=MD5(`pwd`) WHERE `id` = 1 -- 給所有數據加密: UPDATE `testmd5` SET `pwd`=MD5(`pwd`)-- 插入數據的同時也完成加密: INSERT INTO `testmd5`(`id`,`name`,`pwd`) VALUES(10,'小李',MD5('123456'))-- 如何校驗:將用戶傳遞進來的密碼進行md5加密,然后對比加密后的值 SELECT * FROM `testmd5` WHERE `pwd` = MD5('123456') SELECT * FROM `testmd5` WHERE `pwd` = MD5('123456') AND `name`='小張'注意:id = 1的數據被加密了兩次,所以它的pwd字段和其他的不一樣
課件截圖:
27. SELECT小結
對應第四章剛開始的SELECT語法。
第四章主要講了DQL(Database Query Language)數據庫查詢語言,關鍵字就是SELECT,后面跟了很多個可選項,總結下來就是:
- 16 &17:SELECT [去重-DISTINCT] 要查詢的字段 FROM 數據表A (表和字段可用AS取別名)
- 20:xxx(INNER) JOIN 要連接的表B ON 交叉條件 – 連接查詢
- 18 & 19 & 23:WHERE 條件 – 篩選條件(如果有多個篩選條件,就在后面加AND關鍵字,不要加逗號,)模糊查詢(關鍵字LIKE和關鍵字IN)> 或者子查詢語句)
- 25:[GROUP BY …] – 通過哪個字段來分組
- 25:[HAVING] – 過濾分組后的信息,條件和where是一樣的,區別就是先后位置不同
- 22:ORDER BY – (通過哪個字段排序)[升序ASC / 降序DESC]
- 22:LIMIT startIndex, pageSize – 分頁
上面的可選部分順序很重要;
HAVING 和 WHERE的區別就在于先后位置不同。
業務層面:
查詢:跨表、跨數據庫…
內置函數小結:
只試了第一部分:數值函數,剩下的沒試;
此外還有**24.常用函數(不常用) 和 25. 聚合函數(常用)**也是MySQL函數。
六、事務
28.事務ACID原則、臟讀、不可重復讀、幻讀
第六章的內容見:數據庫學習筆記2
總結
- 上一篇: 封建制度与奴隶制度的区别
- 下一篇: mysql 事件跟踪_ORACLE 事件