一、鎖概述
鎖是計算機(jī)協(xié)調(diào)多個進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制(避免爭搶)。
在數(shù)據(jù)庫中,除傳統(tǒng)的計算資源(如 CPU、RAM、I/O 等)的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資源。如何保證數(shù)據(jù)并發(fā)訪問的一致性、有效性是所有數(shù)據(jù)庫必須解決的一個問題,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個重要因素。從這個角度來說,鎖對數(shù)據(jù)庫而言顯得尤其重要,也更加復(fù)雜。
二、鎖分類
從對數(shù)據(jù)操作的粒度分:
- 1、表鎖:操作時,會鎖定整個表。
- 2、行鎖:操作時,會鎖定當(dāng)前操作行。
從對數(shù)據(jù)操作的類型分:
- 1、讀鎖(共享鎖):針對同一份數(shù)據(jù),多個讀操作可以同時進(jìn)行而不會互相影響。
- 2、寫鎖(排它鎖):當(dāng)前操作沒有完成之前,它會阻斷其他寫鎖和讀鎖。
三、Mysql 鎖
相對其他數(shù)據(jù)庫而言,MySQL的鎖機(jī)制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機(jī)制。下表中羅列出了各存儲引擎對鎖的支持情況:
| 存儲引擎 | 表級鎖 | 行級鎖 | 頁面鎖 |
|---|---|---|---|
| MyISAM | 支持 | 不支持 | 不支持 |
| InnoDB | 支持 | 支持 | 不支持 |
| MEMORY | 支持 | 不支持 | 不支持 |
| BDB | 支持 | 不支持 | 支持 |
MySQL這3種鎖的特性可大致歸納如下 :
| 鎖類型 | 特點 |
|---|---|
| 表級鎖 | 偏向MyISAM 存儲引擎,開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。 |
| 行級鎖 | 偏向InnoDB 存儲引擎,開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。 |
| 頁面鎖 | 開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。 |
從上述特點可見,很難籠統(tǒng)地說哪種鎖更好,只能就具體應(yīng)用的特點來說哪種鎖更合適!僅從鎖的角度來說:表級鎖更適合于以查詢?yōu)橹?,只有少量按索引條件更新數(shù)據(jù)的應(yīng)用,如Web 應(yīng)用;而行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時又有并查詢的應(yīng)用,如一些在線事務(wù)處理(OLTP)系統(tǒng)。
四、MyISAM 表鎖
MyISAM 存儲引擎只支持表鎖,這也是MySQL開始幾個版本中唯一支持的鎖類型。
4.1、如何加表鎖
MyISAM 在執(zhí)行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執(zhí)行更新操作(UPDATE、DELETE、INSERT 等)前,會自動給涉及的表加寫鎖,這個過程并不需要用戶干預(yù),因此,用戶一般不需要直接用 LOCK TABLE 命令給 MyISAM 表顯式加鎖。
顯示加表鎖語法:
加讀鎖 : lock table table_name read;
加寫鎖 : lock table table_name write;
4.2、讀鎖案例
準(zhǔn)備環(huán)境
create database demo_03 default charset=utf8mb4;
use demo_03;
CREATE TABLE `tb_book` (
`id` INT(11) auto_increment,
`name` VARCHAR(50) DEFAULT NULL,
`publish_time` DATE DEFAULT NULL,
`status` CHAR(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;
INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'java編程思想','2088-08-01','1');
INSERT INTO tb_book (id, name, publish_time, status) VALUES(NULL,'solr編程思想','2088-08-08','0');
CREATE TABLE `tb_user` (
`id` INT(11) auto_increment,
`name` VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=myisam DEFAULT CHARSET=utf8 ;
INSERT INTO tb_user (id, name) VALUES(NULL,'令狐沖');
INSERT INTO tb_user (id, name) VALUES(NULL,'田伯光');
客戶端 一:
- 1、獲得tb_book 表的讀鎖
lock table tb_book read;
- 2、執(zhí)行查詢操作
select * from tb_book;

可以正常執(zhí)行 , 查詢出數(shù)據(jù)。
客戶端 二 :
- 3、執(zhí)行查詢操作
select * from tb_book;

客戶端 一 :
- 4、查詢未鎖定的表
select name from tb_seller;

客戶端 二 :
- 5、查詢未鎖定的表
select name from tb_seller;

可以正常查詢出未鎖定的表;
客戶端 一 :
- 6、執(zhí)行插入操作
insert into tb_book values(null,'Mysql高級','2088-01-01','1');

執(zhí)行插入, 直接報錯 , 由于當(dāng)前tb_book 獲得的是 讀鎖, 不能執(zhí)行更新操作。
客戶端 二 :
- 7、執(zhí)行插入操作
insert into tb_book values(null,'Mysql高級','2088-01-01','1');

當(dāng)在客戶端一中釋放鎖指令 unlock tables 后 , 客戶端二中的 inesrt 語句 , 立即執(zhí)行 ;
4.3、寫鎖案例
客戶端 一 :
- 1、獲得tb_book 表的寫鎖
lock table tb_book write ;
- 2、執(zhí)行查詢操作
select * from tb_book ;

查詢操作執(zhí)行成功;
- 3、執(zhí)行更新操作
update tb_book set name = 'java編程思想(第二版)' where id = 1;

更新操作執(zhí)行成功 ;
客戶端 二 :
- 4、執(zhí)行查詢操作
select * from tb_book ;

當(dāng)在客戶端一中釋放鎖指令 unlock tables 后,客戶端二中的 select 語句, 立即執(zhí)行 ;

4.4、結(jié)論
鎖模式的相互兼容性如表中所示:

由上表可見:
1、對MyISAM 表的讀操作,不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;
2) 對MyISAM 表的寫操作,則會阻塞其他用戶對同一表的讀和寫操作;
簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀。而寫鎖,則既會阻塞讀,又會阻塞寫。
此外,MyISAM 的讀寫鎖調(diào)度是寫優(yōu)先,這也是MyISAM不適合做寫為主的表的存儲引擎的原因。因為寫鎖后,其他線程不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成永遠(yuǎn)阻塞。
4.5、查看鎖的爭用情況
show open tables;

In_user:表當(dāng)前被查詢使用的次數(shù)。如果該數(shù)為零,則表是打開的,但是當(dāng)前沒有被使用。
Name_locked:表名稱是否被鎖定。名稱鎖定用于取消表或?qū)Ρ磉M(jìn)行重命名等操作。
show status like 'Table_locks%'

Table_locks_immediate:指的是能夠立即獲得表級鎖的次數(shù),每立即獲取鎖,值加1。
Table_locks_waited:指的是不能立即獲取表級鎖而需要等待的次數(shù),每等待一次,該值加1,此值高說明存在著較為嚴(yán)重的表級鎖爭用情況。
五、InnoDB 行鎖
5.1、 行鎖介紹
行鎖特點 :偏向InnoDB 存儲引擎,開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。
InnoDB 與 MyISAM 的最大不同有兩點:一是支持事務(wù);二是采用了行級鎖。
InnoDB 存儲結(jié)構(gòu)
InnoDB 是聚簇索引,也就是 B+樹的葉節(jié)點既存儲了主鍵索引也存儲了數(shù)據(jù)行。而 InnoDB 的二級索引的葉節(jié)點存儲的則是主鍵值,所以通過二級索引查詢數(shù)據(jù)時,還需要拿對應(yīng)的主鍵去聚簇索引中再次進(jìn)行查詢。

5.2、背景知識
事務(wù)及其ACID屬性
事務(wù)是由一組SQL語句組成的邏輯處理單元。
事務(wù)具有以下4個特性,簡稱為事務(wù)ACID屬性。
| ACID屬性 | 含義 |
|---|---|
| 原子性(Atomicity) | 事務(wù)是一個原子操作單元,其對數(shù)據(jù)的修改,要么全部成功,要么全部失敗。 |
| 一致性(Consistent) | 在事務(wù)開始和完成時,數(shù)據(jù)都必須保持一致狀態(tài)。 |
| 隔離性(Isolation) | 數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的 “獨立” 環(huán)境下運(yùn)行。 |
| 持久性(Durable) | 事務(wù)完成之后,對于數(shù)據(jù)的修改是永久的。 |
并發(fā)事務(wù)處理帶來的問題
| 問題 | 含義 |
|---|---|
| 丟失更新(Lost Update) | 當(dāng)兩個或多個事務(wù)選擇同一行,最初的事務(wù)修改的值,會被后面的事務(wù)修改的值覆蓋。 |
| 臟讀(Dirty Reads) | 當(dāng)一個事務(wù)正在訪問數(shù)據(jù),并且對數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務(wù)也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。 |
| 不可重復(fù)讀(NonRepeatable Reads) | 一個事務(wù)在讀取某些數(shù)據(jù)后的某個時間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)和以前讀出的數(shù)據(jù)不一致。 |
| 幻讀(Phantom Reads) | 一個事務(wù)按照相同的查詢條件重新讀取以前查詢過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù)。 |
事務(wù)隔離級別
為了解決上述提到的事務(wù)并發(fā)問題,數(shù)據(jù)庫提供一定的事務(wù)隔離機(jī)制來解決這個問題。
數(shù)據(jù)庫的事務(wù)隔離越嚴(yán)格,并發(fā)副作用越小,但付出的代價也就越大,因為事務(wù)隔離實質(zhì)上就是使用事務(wù)在一定程度上“串行化” 進(jìn)行,這顯然與“并發(fā)” 是矛盾的。
數(shù)據(jù)庫的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟寫、臟讀、不可重復(fù)讀、幻讀這幾類問題。
| 隔離級別 | 丟失更新 | 臟讀 | 不可重復(fù)讀 | 幻讀 |
|---|---|---|---|---|
| Read uncommitted | × | √ | √ | √ |
| Read committed | × | × | √ | √ |
| Repeatable read(默認(rèn)) | × | × | × | √ |
| Serializable | × | × | × | × |
備注 : √ 代表可能出現(xiàn) , × 代表不會出現(xiàn) 。
Mysql 的數(shù)據(jù)庫的默認(rèn)隔離級別為 Repeatable read , 查看方式:
show variables like 'tx_isolation';

5.3、InnoDB 的行鎖模式
InnoDB 實現(xiàn)了以下兩種類型的行鎖。
共享鎖(S):又稱為讀鎖,簡稱S鎖,共享鎖就是多個事務(wù)對于同一數(shù)據(jù)可以共享一把鎖,都能訪問到數(shù)據(jù),但是只能讀不能修改。
排他鎖(X):又稱為寫鎖,簡稱X鎖,排他鎖就是不能與其他鎖并存,如一個事務(wù)獲取了一個數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務(wù)是可以對數(shù)據(jù)就行讀取和修改。
對于UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數(shù)據(jù)集加排他鎖(X);
對于普通SELECT語句,InnoDB不會加任何鎖;
可以通過以下語句顯示給記錄集加共享鎖或排他鎖 。
共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他鎖(X) :SELECT * FROM table_name WHERE ... FOR UPDATE
5.4、 案例準(zhǔn)備工作
create table test_innodb_lock(
id int(11),
name varchar(16),
sex varchar(1)
)engine = innodb default charset=utf8;
insert into test_innodb_lock values(1,'100','1');
insert into test_innodb_lock values(3,'3','1');
insert into test_innodb_lock values(4,'400','0');
insert into test_innodb_lock values(5,'500','1');
insert into test_innodb_lock values(6,'600','0');
insert into test_innodb_lock values(7,'700','0');
insert into test_innodb_lock values(8,'800','1');
insert into test_innodb_lock values(9,'900','1');
insert into test_innodb_lock values(1,'200','0');
create index idx_test_innodb_lock_id on test_innodb_lock(id);
create index idx_test_innodb_lock_name on test_innodb_lock(name);
5.5、行鎖基本演示


5.6、無索引行鎖升級為表鎖
如果不通過索引條件檢索數(shù)據(jù),那么InnoDB將對表中的所有記錄加鎖,實際效果跟表鎖一樣。
查看當(dāng)前表的索引:
show index from test_innodb_lock ;


由于 執(zhí)行更新時 , name字段本來為varchar類型, 我們是作為數(shù)組類型使用,存在類型轉(zhuǎn)換,索引失效,最終行鎖變?yōu)楸礞i;
5.7、間隙鎖危害
當(dāng)我們用范圍條件,而不是使用相等條件檢索數(shù)據(jù),并請求共享或排他鎖時,InnoDB會給符合條件的已有數(shù)據(jù)進(jìn)行加鎖; 對于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做 "間隙(GAP)" , InnoDB也會對這個 "間隙" 加鎖,這種鎖機(jī)制就是所謂的 間隙鎖(Next-Key鎖) 。
示例 :

5.8、Gap lock
還有一種間隙鎖的現(xiàn)象:
比如,更新用戶年齡的例子,如果 id = 49 這條記錄不存在,這個 SQL 語句還會加鎖嗎?答案是有可能,這取決于數(shù)據(jù)庫的隔離級別。這種情況下,在 RC 隔離級別不會加任何鎖,在 RR 隔離級別會在 id = 49 前后兩個索引之間加上間隙鎖。
間隙鎖是一種加在兩個索引之間的鎖,或者加在第一個索引之前,或最后一個索引之后的間隙。這個間隙可以跨一個索引記錄,多個索引記錄,甚至是空的。使用間隙鎖可以防止其他事務(wù)在這個范圍內(nèi)插入或修改記錄,保證兩次讀取這個范圍內(nèi)的記錄不會變,從而不會出現(xiàn)幻讀現(xiàn)象。
值得注意的是,間隙鎖和間隙鎖之間是互不沖突的,間隙鎖唯一的作用就是為了防止其他事務(wù)的插入,所以加間隙 S 鎖和加間隙 X 鎖沒有任何區(qū)別。
5.9、InnoDB 行鎖爭用情況
show status like 'innodb_row_lock%';

- Innodb_row_lock_current_waits:當(dāng)前正在等待鎖定的數(shù)量。
- Innodb_row_lock_time:從系統(tǒng)啟動到現(xiàn)在鎖定總時間長度。
- Innodb_row_lock_time_avg:每次等待所花平均時長。
- Innodb_row_lock_time_max:從系統(tǒng)啟動到現(xiàn)在等待最長的一次所花的時間。
- Innodb_row_lock_waits:系統(tǒng)啟動后到現(xiàn)在總共等待的次數(shù)。
當(dāng)?shù)却拇螖?shù)很高,而且每次等待的時長也不小的時候,我們就需要分析系統(tǒng)中為什么會有如此多的等待,然后根據(jù)分析結(jié)果著手制定優(yōu)化計劃。
5.10、InnoDB 行鎖總結(jié):
InnoDB存儲引擎由于實現(xiàn)了行級鎖定,雖然在鎖定機(jī)制的實現(xiàn)方面帶來了性能損耗可能比表鎖會更高一些,但是在整體并發(fā)處理能力方面要遠(yuǎn)遠(yuǎn)優(yōu)于MyISAM的表鎖的。當(dāng)系統(tǒng)并發(fā)量較高的時候,InnoDB的整體性能和MyISAM相比就會有比較明顯的優(yōu)勢。
但是,InnoDB的行級鎖同樣也有其脆弱的一面,當(dāng)我們使用不當(dāng)?shù)臅r候,可能會讓InnoDB的整體性能表現(xiàn)不僅不能比MyISAM高,甚至可能會更差。
優(yōu)化建議:
- 1、盡可能讓所有數(shù)據(jù)檢索都能通過索引來完成,避免無索引行鎖升級為表鎖。
- 2、合理設(shè)計索引,盡量縮小鎖的范圍。
- 3、盡可能減少索引條件,及索引范圍,避免間隙鎖。
- 4、盡量控制事務(wù)大小,減少鎖定資源量和時間長度。
- 5、盡可使用低級別事務(wù)隔離(但是需要業(yè)務(wù)層面滿足需求)。
六、常用SQL技巧
6.1、SQL執(zhí)行順序
編寫順序
SELECT DISTINCT
<select list>
FROM
<left_table> <join_type>
JOIN
<right_table>
ON
<join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT
<limit_params>
執(zhí)行順序
FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT DISTINCT <select list>
ORDER BY <order_by_condition>
LIMIT <limit_params>
事實上,sql并不是按照我們的書寫順序來從前往后、左往右依次執(zhí)行的,它是按照固定的順序解析的,主要的作用就是從上一個階段的執(zhí)行返回結(jié)果來提供給下一階段使用,sql在執(zhí)行的過程中會有不同的臨時中間表,一般是按照如下順序:

6.2、正則表達(dá)式使用
正則表達(dá)式(Regular Expression)是指一個用來描述或者匹配一系列符合某個句法規(guī)則的字符串的單個字符串。
| 符號 | 含義 | |
|---|---|---|
| ^ | 在字符串開始處進(jìn)行匹配 | |
| $ | 在字符串末尾處進(jìn)行匹配 | |
| . | 匹配任意單個字符, 包括換行符 | |
| [...] | 匹配出括號內(nèi)的任意字符 | |
| [^...] | 匹配不出括號內(nèi)的任意字符 | |
| a* | 匹配零個或者多個a(包括空串) | |
| a+ | 匹配一個或者多個a(不包括空串) | |
| a? | 匹配零個或者一個a | |
| a1 | a2 | 匹配a1或a2 |
| a(m) | 匹配m個a | |
| a(m,) | 至少匹配m個a | |
| a(m,n) | 匹配m個a 到 n個a | |
| a(,n) | 匹配0到n個a | |
| (...) | 將模式元素組成單一元素 |
select * from emp where name regexp '^T';
select * from emp where name regexp '2$';
select * from emp where name regexp '[uvw]';
6.3、MySQL 常用函數(shù)
數(shù)字函數(shù)
| 函數(shù)名稱 | 作 用 |
|---|---|
| ABS | 求絕對值 |
| SQRT | 求二次方根 |
| MOD | 求余數(shù) |
| CEIL 和 CEILING | 兩個函數(shù)功能相同,都是返回不小于參數(shù)的最小整數(shù),即向上取整 |
| FLOOR | 向下取整,返回值轉(zhuǎn)化為一個BIGINT |
| RAND | 生成一個0~1之間的隨機(jī)數(shù),傳入整數(shù)參數(shù)是,用來產(chǎn)生重復(fù)序列 |
| ROUND | 對所傳參數(shù)進(jìn)行四舍五入 |
| SIGN | 返回參數(shù)的符號 |
| POW 和 POWER | 兩個函數(shù)的功能相同,都是所傳參數(shù)的次方的結(jié)果值 |
| SIN | 求正弦值 |
| ASIN | 求反正弦值,與函數(shù) SIN 互為反函數(shù) |
| COS | 求余弦值 |
| ACOS | 求反余弦值,與函數(shù) COS 互為反函數(shù) |
| TAN | 求正切值 |
| ATAN | 求反正切值,與函數(shù) TAN 互為反函數(shù) |
| COT | 求余切值 |
字符串函數(shù)
| 函數(shù)名稱 | 作 用 |
|---|---|
| LENGTH | 計算字符串長度函數(shù),返回字符串的字節(jié)長度 |
| CONCAT | 合并字符串函數(shù),返回結(jié)果為連接參數(shù)產(chǎn)生的字符串,參數(shù)可以使一個或多個 |
| INSERT | 替換字符串函數(shù) |
| LOWER | 將字符串中的字母轉(zhuǎn)換為小寫 |
| UPPER | 將字符串中的字母轉(zhuǎn)換為大寫 |
| LEFT | 從左側(cè)字截取符串,返回字符串左邊的若干個字符 |
| RIGHT | 從右側(cè)字截取符串,返回字符串右邊的若干個字符 |
| TRIM | 刪除字符串左右兩側(cè)的空格 |
| REPLACE | 字符串替換函數(shù),返回替換后的新字符串 |
| SUBSTRING | 截取字符串,返回從指定位置開始的指定長度的字符換 |
| REVERSE | 字符串反轉(zhuǎn)(逆序)函數(shù),返回與原始字符串順序相反的字符串 |
日期函數(shù)
| 函數(shù)名稱 | 作 用 |
|---|---|
| CURDATE 和 CURRENT_DATE | 兩個函數(shù)作用相同,返回當(dāng)前系統(tǒng)的日期值 |
| CURTIME 和 CURRENT_TIME | 兩個函數(shù)作用相同,返回當(dāng)前系統(tǒng)的時間值 |
| NOW 和 SYSDATE | 兩個函數(shù)作用相同,返回當(dāng)前系統(tǒng)的日期和時間值 |
| MONTH | 獲取指定日期中的月份 |
| MONTHNAME | 獲取指定日期中的月份英文名稱 |
| DAYNAME | 獲取指定曰期對應(yīng)的星期幾的英文名稱 |
| DAYOFWEEK | 獲取指定日期對應(yīng)的一周的索引位置值 |
| WEEK | 獲取指定日期是一年中的第幾周,返回值的范圍是否為 0?52 或 1?53 |
| DAYOFYEAR | 獲取指定曰期是一年中的第幾天,返回值范圍是1~366 |
| DAYOFMONTH | 獲取指定日期是一個月中是第幾天,返回值范圍是1~31 |
| YEAR | 獲取年份,返回值范圍是 1970?2069 |
| TIME_TO_SEC | 將時間參數(shù)轉(zhuǎn)換為秒數(shù) |
| SEC_TO_TIME | 將秒數(shù)轉(zhuǎn)換為時間,與TIME_TO_SEC 互為反函數(shù) |
| DATE_ADD 和 ADDDATE | 兩個函數(shù)功能相同,都是向日期添加指定的時間間隔 |
| DATE_SUB 和 SUBDATE | 兩個函數(shù)功能相同,都是向日期減去指定的時間間隔 |
| ADDTIME | 時間加法運(yùn)算,在原始時間上添加指定的時間 |
| SUBTIME | 時間減法運(yùn)算,在原始時間上減去指定的時間 |
| DATEDIFF | 獲取兩個日期之間間隔,返回參數(shù) 1 減去參數(shù) 2 的值 |
| DATE_FORMAT | 格式化指定的日期,根據(jù)參數(shù)返回指定格式的值 |
| WEEKDAY | 獲取指定日期在一周內(nèi)的對應(yīng)的工作日索引 |
聚合函數(shù)
| 函數(shù)名稱 | 作 用 |
|---|---|
| MAX | 查詢指定列的最大值 |
| MIN | 查詢指定列的最小值 |
| COUNT | 統(tǒng)計查詢結(jié)果的行數(shù) |
| SUM | 求和,返回指定列的總和 |
| AVG | 求平均值,返回指定列數(shù)據(jù)的平均值 |
參考:
https://www.imooc.com/article/295953
https://blog.csdn.net/org_hjh/article/details/108901385
http://blog.itpub.net/31556440/viewspace-2642668/
https://www.cnblogs.com/leedaily/p/8378779.html
https://www.mscto.com/data/459802.html