炸裂!MySQL 82 張圖帶你飛

以前兩篇文章帶你瞭解了 MySQL 的基礎語法和 MySQL 的進階內容,那麼這篇文章咱們來了解一下 MySQL 中的高級內容。mysql

其餘文章:git

138 張圖帶你 MySQL 入門程序員

47 張圖帶你 MySQL 進階!!!github

炸裂!MySQL 82 張圖帶你飛!面試

本文思惟導圖以下。正則表達式

事務控制和鎖定語句

咱們知道,MyISAM 和 MEMORY 存儲引擎支持表級鎖定(table-level locking),InnoDB 存儲引擎支持行級鎖定(row-level locking),BDB 存儲引擎支持頁級鎖定(page-level locking)。各個鎖定級別的特色以下sql

頁級鎖:銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常數據庫

表級鎖:表級鎖是對整張表進行加鎖,MyISAM 和 MEMORY 主要支持表級鎖,表級鎖加鎖快,不會出現死鎖,鎖的粒度比較粗,併發度最低安全

行級鎖:行級鎖能夠說是 MySQL 中粒度最細的一種鎖了,InnoDB 支持行級鎖,行級鎖容易發生死鎖,併發度比較好,同時鎖的開銷也比較大。服務器

MySQL 默認狀況下支持表級鎖定和行級鎖定。可是在某些狀況下須要手動控制事務以確保整個事務的完整性,下面咱們就來探討一下事務控制。可是在探討事務控制以前咱們先來認識一下兩個鎖定語句

鎖定語句

MySQL 的鎖定語句主要有兩個 LockunLock,Lock Tables 可用於鎖定當前線程的表,就跟 Java 語法中的 Lock 鎖的用法是同樣的,若是表鎖定,意味着其餘線程不能再操做表,直到鎖定被釋放爲止。以下圖所示

lock table cxuan005 read;
複製代碼

咱們鎖定了 cxuan005 的 read 鎖,而後這時咱們再進行一次查詢,看看是否可以執行這條語句

select * from cxuan005 where id = 111;
複製代碼

能夠看到,在進行 read 鎖定了,咱們仍舊可以執行查詢語句。

如今咱們另外起一個窗口,至關於另起了一個線程來進行查詢操做。

select * from cxuan005;
複製代碼

這是第二個窗口執行查詢的結果,能夠看到,在一個線程執行 read 鎖定後,其餘線程仍然能夠進行表的查詢操做。

那麼第二個線程可否執行更新操做呢?咱們來看一下

update cxuan005 set info='cxuan' where id = 111;
複製代碼

發生了什麼?怎麼沒有提示結果呢?其實這個狀況下表示 cxuan005 已經被加上了 read 鎖,因爲當前線程不是持有鎖的線程,因此當前線程沒法執行更新。

解鎖語句

如今咱們把窗口切換成持有 read 鎖的線程,來進行 read 鎖的解鎖

unlock tables;
複製代碼

在解鎖完成前,進行更新的線程會一直等待,直到解鎖完成後,纔會進行更新。咱們能夠看一下更新線程的結果。

能夠看到,線程已經更新完畢,咱們看一下更新的結果

select * from cxuan005 where id = 111;
複製代碼

如上圖所示,id = 111 的值已經被更新成了 cxuan。

事務控制

事務(Transaction) 是訪問和更新數據庫的基本執行單元,一個事務中可能會包含多個 SQL 語句,事務中的這些 SQL 語句要麼都執行,要麼都不執行,而 MySQL 它是一個關係型數據庫,它天然也是支持事務的。事務同時也是區分關係型數據庫和非關係型數據庫的一個重要的方面。

在 MySQL 事務中,主要涉及的語法包含 SET AUTOCOMMIT、START TRANSACTION、COMMIT 和 ROLLBACK 等。

自動提交

在 MySQL 中,事務默認是自動提交(Autocommit)的,以下所示

show variables like 'autocommit';
複製代碼

在自動提交的模式下,每一個 SQL 語句都會看成一個事務執行提交操做,例如咱們上面使用的更新語句

update cxuan005 set info='cxuan' where id = 111;
複製代碼

若是想要關閉數據庫的自動提交應該怎麼作呢?

其實,MySQL 是能夠關閉自動提交的,你能夠執行

set autocommit = 0;
複製代碼

而後咱們再看一下自動提交是否關閉了,再次執行一下 show variables like 'autocommit' 語句

能夠看到,自動提交已經關閉了,再次執行

set autocommit = 1;
複製代碼

會再次開啓自動提交。

這裏注意一下特殊操做。

在 MySQL 中,存在一些特殊的命令,若是在事務中執行了這些命令,會立刻強制執行 commit 提交事務;好比 DDL 語句(create table/drop table/alter/table)、lock tables 語句等等。

不過,經常使用的 select、insert、update 和 delete命令,都不會強制提交事務。

手動提交

若是須要手動 commit 和 rollback 的話,就須要明確的事務控制語句了。

典型的 MySQL 事務操做以下

start transaction;
... # 一條或者多條語句
commit;
複製代碼

上面代碼中的 start transaction 就是事務的開始語句,編寫 SQL 後會調用 commit 提交事務,而後將事務統一執行,若是 SQL 語句出現錯誤會自動調用 Rollback 進行回滾。

下面咱們就經過示例來演示一下 MySQL 的事務,一樣的,咱們須要啓動兩個窗口來演示,爲了便於區分,咱們使用 mysql01 和 mysql02 來命名。

咱們用 start transaction 命令啓動一個事務,而後再 cxuan005 表中插入一條數據,此時 mysql02 不作任何操做。涉及的 SQL 語句以下。

start transaction;
複製代碼

而後執行

select * from cxuan005;
複製代碼

查詢一下 cxuan005 中的數據

嗯。。。不少長度太長了,如今咱們把全部的 info 數據都更新爲 cxuan 。

update cxuan005 set info='cxuan';
複製代碼

更新完畢後,咱們先不提交事務,分別在 mysql01 和 mysql02 中進行查詢,發現只有 mysql01 窗口中的查詢已經生效,而 mysql02 中仍是更新前的數據

如今咱們在 mysql01 中 commit 當前事務,而後在 mysql02 中查詢,發現數據已經被修改了。

除了 commit 以外,MySQL 中還有 commit and chain 命令,這個命令會提交當前事務而且從新開啓一個新的事務。以下代碼所示

start transaction; # 開啓一個新的事務
insert into cxuan005(id,info) values (555,'cxuan005'); # 插入一條數據
commit and chain; # 提交當前事務並從新開啓一個事務
複製代碼

上面是一個事務操做,在 commit and chain 鍵入後,咱們能夠再次執行 SQL 語句

update cxuan005 set info = 'cxuan' where id = 555;
commit;
複製代碼

而後再次查詢

select * from cxuan005;
複製代碼

執行後,能夠發現,咱們僅僅使用了一個 start transaction 命令就執行了兩次事務操做。

若是在手動提交的事務中,你發現有一條 SQL 語句寫的不正確或者有其餘緣由須要回滾,那麼此時你就會用到 rollback 語句,它會回滾當前事務,至關於什麼也沒發生。以下代碼所示。

start transaction;
delete from cxuan005 where id = 555;
rollback;
複製代碼

這裏切忌一點:delete 刪除語句必定要加 where ,不加 where 語句的刪除就是耍流氓。

在同一個事務操做中,最好使用相同存儲引擎的表,若是使用不一樣存儲引擎的表後,rollback 語句會對非事務類型的表進行特別處理,所以 commit 、rollback 只能對事務類型的表進行提交和回滾。

咱們提交的事務通常都會被記錄到二進制的日誌中,可是若是一個事務中包含非事務類型的表,那麼回滾操做也會被記錄到二進制日誌中,以確保非事務類型的表能夠被複制到從數據庫中。

這裏解釋一下什麼是事務表和非事務表

事務表和非事務表

事務表故名思義就是支持事務的表,支不支持事務和 MySQL 的存儲類型有關,通常狀況下,InnoDB 存儲引擎的表是支持事務的,關於 InnoDB 的知識,咱們會在後面詳細介紹。

非事務表相應的就是不支持事務的表,在 MySQL 中,存儲引擎 MyISAM 是不支持事務的,非事務表的特色是不支持回滾。

對於回滾的話,還要講一點就是 SAVEPOINT,它能指定事務回滾的一部分,可是不能指定事務提交的一部分。 SAVEPOINT 能夠指定多個,在知足不一樣條件的同時,回滾不一樣的 SAVEPOINT。須要注意的是,若是定義了兩個相同名稱的 SAVEPOINT,則後面定義的 SAVEPOINT 會覆蓋以前的定義。若是 SAVEPOINT 再也不須要的話,能夠經過 RELEASE SAVEPOINT 來進行刪除。刪除後的 SAVEPOINT 不能再執行 ROLLBACK TO SAVEPOINT 命令。

咱們經過一個示例來進行模擬不一樣的 SAVEPOINT

首先先啓動一個事務 ,向 cxuan005 中插入一條數據,而後進行查詢,那麼是能夠查詢到這條記錄的

start transaction;
insert into cxuan005(id,info) values(666,'cxuan666');
select * from cxuan005 where id = 666;
複製代碼

查詢以後的記錄以下

而後咱們定義一個 SAVEPOINT,以下所示

savepoint test;
複製代碼

而後繼續插入一條記錄

insert into cxuan005(id,info) values(777,'cxuan777');
複製代碼

此時就能夠查詢到兩條新增記錄了,id 是 666 和 777 的記錄。

select * from cxuan005 where id = 777;
複製代碼

那麼咱們能夠回滾到剛剛定義的 SAVEPOINT

rollback to savepoint test;
複製代碼

再次查詢 cxuan005 這個表,能夠看到,只有 id=666 的這條記錄插入進來了,說明 id=777 這條記錄已經被回滾了。

此時咱們看到的都是 mysql01 中事務尚未提交前的狀態,因此這時候 mysql02 中執行查詢操做是看不到 666 這條記錄的。

而後咱們在 mysql01 中執行 commit 操做,那麼此時在 mysql02 中就能夠查詢到這條記錄了。

SQL 安全問題

SQL 安全問題應該是咱們程序員比較忽視的一個地方了。平常開發中,咱們通常只會關心 SQL 能不能解決咱們的業務問題,能不能把數據查出來,而對於 SQL 問題,咱們通常都認爲這是 DBA 的活,其實咱們 CRUD 程序員也應該瞭解一下 SQL 的安全問題。

SQL 注入簡介

SQL 注入就是利用某些數據庫的外部接口將用戶數據插入到實際的 SQL 中,從而達到入侵數據庫的目的。SQL 注入是一種常見的網絡攻擊的方式,它不是利用操做系統的 BUG 來實現攻擊的。SQL 主要是針對程序員編寫時的疏忽來入侵的。

SQL 注入攻擊有很大的危害,攻擊者能夠利用它讀取、修改或者刪除數據庫內的數據,獲取數據庫中的用戶名和密碼,甚至得到數據庫管理員的權限。而且 SQL 注入通常比較難以防範。

SQL Mode

MySQL 能夠運行在不一樣的 SQL Mode 模式下,不一樣的 SQL Mode 定義了不一樣的 SQL 語法,數據校驗規則,這樣就可以在不一樣的環境中使用 MySQL ,下面咱們就來介紹一下 SQL Mode。

SQL Mode 解決問題

SQL Mode 能夠解決下面這幾種問題

  • 經過設置 SQL Mode,能夠完成不一樣嚴格程度的數據校驗,有效保障數據的準確性。
  • 設置 SQL Mode 爲 ANSI 模式,來保證大多數 SQL 符合標準的 SQL 語法,這樣應用在不一樣數據庫的遷移中,不須要對 SQL 進行較大的改變
  • 數據在不一樣數據庫的遷移中,經過改變 SQL Mode 可以更方便的進行遷移。

下面咱們就經過示例來演示一下 SQL Mode 用法

咱們能夠經過

select @@sql_mode;
複製代碼

來查看默認的 SQL Mode,以下是個人數據庫所支持的 SQL Mode

涉及到不少 SQL Mode,下面是這些 SQL Mode 的解釋

ONLY_FULL_GROUP_BY:這個模式會對 GROUP BY 進行合法性檢查,對於 GROUP BY 操做,若是在SELECT 中的列,沒有在 GROUP BY 中出現,那麼將認爲這個 SQL 是不合法的,由於列不在 GROUP BY 從句中

一樣舉個例子,咱們如今查詢一下 cxuan005 的 id 和 info 字段。

select id,info from cxuan005;
複製代碼

這樣是能夠運行的

而後咱們使用 GROUP BY 字句進行分組,這裏只對 info 進行分組,咱們看一下會出現什麼狀況

select id,info from cxuan005 group by info;
複製代碼

咱們能夠從錯誤緣由中看到,這條 SQL 語句是不符合 ONLY_FULL_GROUP_BY 的這條 SQL Mode 的。由於咱們只對 info 進行分組了,沒有對 id 進行分組,咱們把 SQL 語句改爲以下形式

select id,info from cxuan005 group by id,info;
複製代碼

這樣 SQL 就能正確執行了。

固然,咱們也能夠刪除 sql_mode = ONLY_FULL_GROUP_BY 的這條 Mode,可使用

SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
複製代碼

來進行刪除,刪除後咱們使用分組語句就能夠放飛自我了。

select id,info from cxuan005 group by info;
複製代碼

可是這種作法只是暫時的修改,咱們能夠修改配置文件 my.ini 中的 sql_mode= STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

STRICT_TRANS_TABLES:這就是嚴格模式,在這個模式下會對數據進行嚴格的校驗,錯誤數據不能插入,報error 錯誤。若是不能將給定的值插入到事務表中,則放棄該語句。對於非事務表,若是值出如今單行語句或多行語句的第1行,則放棄該語句。

當使用 innodb 存儲引擎表時,考慮使用 innodb_strict_mode 模式的 sql_mode,它能增量額外的錯誤檢測功能。

NO_ZERO_IN_DATE:這個模式影響着日期中的月份和天數是否能夠爲 0(注意年份是非 0 的),這個模式也取決於嚴格模式是否被啓用。若是這個模式未啓用,那麼日期中的零部分被容許而且插入沒有警告。若是這個模式啓用,那麼日期中的零部分插入被做爲 0000-00-00 而且產生一個警告。

這個模式須要注意下,若是啓用的話,須要 STRICT_TRANS_TABLESNO_ZERO_IN_DATE 同時啓用,不然不起做用,也就是

set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE';
複製代碼

而後咱們換表了,使用 cxuan003 這張表,表結構以下

咱們主要測試日期的使用,在 cxuan003 中插入一條日期爲 0000-00-00 的數據

insert into cxuan003 values(111,'study','0000-00-00');
複製代碼

發現可以執行成功,可是把年月日各自變爲 0 以後再進行插入,則會插入失敗。

insert into cxuan003 values(111,'study','2021-00-00');
複製代碼

insert into cxuan003 values(111,'study','2021-01-00');
複製代碼

這些組合有不少,我這裏就再也不細緻演示了,讀者能夠自行測試。

若是要插入 0000-00-00 這樣的數據,必須設置 NO_ZERO_IN_DATENO_ZERO_DATE

ERROR_FOR_DIVISION_BY_ZERO:若是這個模式未啓用,那麼零除操做將會插入空值而且不會產生警告;若是這個模式啓用,零除操做插入空值併產生警告;若是這個模式和嚴格模式都啓用,零除從操做將會產生一個錯誤。

NO_AUTO_CREATE_USER:禁止使用 grant 語句自動建立用戶,除非認證信息被指定。

NO_ENGINE_SUBSTITUTION:此模式指定當執行 create 語句或者 alter 語句指定的存儲引擎沒有啓用或者沒有編譯時,控制默認存儲引擎的自動切換。默認是啓用狀態的。

SQL Mode 三種做用域

SQL Mode 按做用區域和時間可分爲 3。個級別,分別是會話級別,全局級別,配置(永久生效)級別

咱們上面使用的 SQL Mode 都是 會話級別,會話級別就是當前窗口域有效。它的設置方式是

set @@session.sql_mode='xx_mode'
set session sql_mode='xx_mode'
複製代碼

全局域就是當前會話關閉不失效,可是在 MySQL 重啓後失效。它的設置方式是

set global sql_mode='xx_mode';
set @@global.sql_mode='xx_mode';
複製代碼

配置域就是在 vi /etc/my.cnf 裏面添加

[mysqld]
sql-mode = "xx_mode"
複製代碼

配置域在保存退出後,重啓服務器,便可永久生效。

SQL 正則表達式

正則表達式相信你們應該都用過,不過你在 MySQL 中用過正則表達式嗎?下面咱們就來聊一聊 SQL 中的正則表達式。

正則表達式(Regular Expression) 是指一個用來描述或者匹配字符串的句法規則。正則表達式一般用來檢索和替換某個文本中的文本內容。不少語言都支持正則表達式,MySQL 一樣也不例外,MySQL 利用 REGEXP 命令提供給用戶擴展的正則表達式功能。下面是 MySQL 中正則表達式的一些規則。

下面來演示一下正則表達式的用法

  • ^ 在字符串的開始進行匹配,根據返回的結果來判斷是否匹配,1 = 匹配,0 = 不匹配。下面嘗試匹配字符串 aaaabbbccc 是否以字符串 a 爲開始

    select 'aaaabbbccc' regexp '^a';
    複製代碼

  • 一樣的,$ 會在末尾處進行匹配,以下所示

    select 'aaaabbbccc' regexp 'c$';
    複製代碼

  • . 匹配單個任意字符

    select 'berska' regexp '.s', 'zara' regexp '.a';
    複製代碼

  • [...] 表示匹配括號內的任意字符,示例以下

    select 'whosyourdaddy' regexp '[abc]';
    複製代碼

  • [^...] 匹配括號內不包含的任意字符,和 [...] 是相反的,若是有任何匹配不上,返回 0 ,所有匹配上返回 1。

    select 'x' regexp '[^xyz]';
    複製代碼

  • n* 表示匹配零個或者多個 n 字符串,以下

    select 'aabbcc' regexp 'd*';
    複製代碼

沒有 d 出現也能夠返回 1 ,由於 * 表示 0 或者多個。

  • n+ 表示匹配 1 個或者 n 個字符串

    select 'aabbcc' regexp 'd+';
    複製代碼

  • n? 的用法和 n+ 相似,只不過 n? 能夠匹配空串

常見 SQL 技巧

RAND() 函數

大多數數據庫都會提供產生隨機數的函數,經過這些函數能夠產生隨機數,也可使用從數據庫表中抽取隨機產生的記錄,這對統計分析來講頗有用。

在 MySQL 中,一般使用 RAND() 函數來產生隨機數。RAND() 和 ORDER BY 組合完成數據抽取功能,以下所示。

咱們新建一張表用於數據檢索。

CREATE TABLE `clerk_Info` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `salary` decimal(10,2) DEFAULT NULL,
  `companyId` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
複製代碼

而後插入一些數據,插入完成後的數據以下。

而後咱們可使用 RAND() 函數進行隨機檢索數據行

select * from clerk_info order by rand();
複製代碼

檢索完成後的數據以下

屢次查詢後發現每次檢索的數據順序都是隨機的。

這個函數多用於隨機抽樣,好比選取必定數量的樣本在進行隨機排序,須要用到 limit 關鍵字。

GROUP BY + WITH ROLLUP

咱們常用 GROUP BY 語句,可是你用過 GROUP BYWITH ROLLUP 一塊兒使用的嗎?使用 GROUP BY 和 WITH ROLLUP 字句能夠檢索出更多的分組集合信息。

咱們仍舊對 clerk_info 表進行操做,咱們對 name 和 salary 進行分組統計工資總數。

select name,sum(salary) from clerk_info group by name with rollup;
複製代碼

能夠看到上面的表按照 name 進行分組,而後再對 money 進行統計。

也就是說 GROUP BY 語句執行完成後能夠知足用戶想要的任何一個分組以及分組組合的聚合信息值。

這裏須要注意一點,不能同時使用 ORDER BY 字句對結果進行排序,ROLLUP 和 ORDER BY 是互斥的。

數據庫名、表名大小寫問題

在 MySQL 中,數據庫中的每一個表至少對應數據庫目錄中的一個文件,固然這取決於存儲引擎的實現了。不一樣的操做系統對大小寫的敏感性決定了數據庫和表名的大小寫的敏感性。在 UNIX 操做系統中是對大小寫敏感的,所以數據庫名和表名也是具備敏感性的,而到了 Windows 則不存在敏感性問題,由於 Windows 操做系統自己對大小寫不敏感。列、索引、觸發器在任何平臺上都對大小寫不敏感。

在 MySQL 中,數據庫名和表名是由 lower_case_tables_name 系統變量決定的。能夠在啓動 mysqld 時設置這個系統變量。下面是 lower_case_tables_name 的值。

若是隻在一個平臺上使用 MySQL 的話,一般不須要修改 lower_case_tables_name 變量。若是想要在不一樣系統系統之間遷移表就會涉及到大小寫問題,由於 UNIX 中 clerk_info 和 CLERK_INFO 被認爲是兩個不一樣的表,而 Windows 中則認爲是一個。在 UNIX 中使用 lower_case_tables_name=0, 而在 Windows 中使用lower_case_tables_name=2,這樣能夠保留數據庫名和表名的大小寫,可是不能保證全部的 SQL 查詢中使用的表名和數據庫名的大小寫相同。若是 SQL 語句中沒有正確引用數據庫名和表名的大小寫,那麼雖然在 Windows 中能正確執行,可是若是將查詢轉移到 UNIX 中,大小寫不正確,將會致使查詢失敗。

外鍵問題

這裏須要注意一個問題,InnoDB 存儲引擎是支持外鍵的,而 MyISAM 存儲引擎是不支持外鍵的,所以在 MyISAM 中設置外鍵會不起做用。

MySQL 經常使用函數

下面咱們來了解一下 MySQL 函數,MySQL 函數也是咱們平常開發過程當中常用的,選用合適的函數可以提升咱們的開發效率,下面咱們就來一塊兒認識一下這些函數

字符串函數

字符串函數是最經常使用的一種函數了,MySQL 也是支持不少種字符串函數,下面是 MySQL 支持的字符串函數表

函數 功能
LOWER 將字符串全部字符變爲小寫
UPPER 將字符串全部字符變爲大寫
CONCAT 進行字符串拼接
LEFT 返回字符串最左邊的字符
RIGHT 返回字符串最右邊的字符
INSERT 字符串替換
LTRIM 去掉字符串左邊的空格
RTRIM 去掉字符串右邊的空格
REPEAT 返回重複的結果
TRIM 去掉字符串行尾和行頭的空格
SUBSTRING 返回指定的字符串
LPAD 用字符串對最左邊進行填充
RPAD 用字符串對最右邊進行填充
STRCMP 比較字符串 s1 和 s2
REPLACE 進行字符串替換

下面經過具體的示例演示一下每一個函數的用法

  • LOWER(str) 和 UPPER(str) 函數:用於轉換大小寫

  • CONCAT(s1,s2 ... sn) :把傳入的參數拼接成一個字符串

上面把 c xu an 拼接成爲了一個字符串,另外須要注意一點,任何和 NULL 進行字符串拼接的結果都是 NULL。

  • LEFT(str,x) 和 RIGHT(str,x) 函數:分別返回字符串最左邊的 x 個字符和最右邊的 x 個字符。若是第二個參數是 NULL,那麼將不會返回任何字符串

  • INSERT(str,x,y,instr) : 將字符串 str 從指定 x 的位置開始, 取 y 個長度的字串替換爲 instr。

  • LTRIM(str) 和 RTRIM(str) 分別表示去掉字符串 str 左側和右側的空格

  • REPEAT(str,x) 函數:返回 str 重複 x 次的結果

  • TRIM(str) 函數:用於去掉目標字符串的空格

  • SUBSTRING(str,x,y) 函數:返回從字符串 str 中第 x 位置起 y 個字符長度的字符串

  • LPAD(str,n,pad) 和 RPAD(str,n,pad) 函數:用字符串 pad 對 str 左邊和右邊進行填充,直到長度爲 n 個字符長度

  • STRCMP(s1,s2) 用於比較字符串 s1 和 s2 的 ASCII 值大小。若是 s1 < s2,則返回 -1;若是 s1 = s2 ,返回 0 ;若是 s1 > s2 ,返回 1。

  • REPLACE(str,a,b) : 用字符串 b 替換字符串 str 種全部出現的字符串 a

數值函數

MySQL 支持數值函數,這些函數可以處理不少數值運算。下面咱們一塊兒來學習一下 MySQL 中的數值函數,下面是全部的數值函數

函數 功能
ABS 返回絕對值
CEIL 返回大於某個值的最大整數值
MOD 返回模
ROUND 四捨五入
FLOOR 返回小於某個值的最大整數值
TRUNCATE 返回數字截斷小數的結果
RAND 返回 0 - 1 的隨機值

下面咱們仍是以實踐爲主來聊一聊這些用法

  • ABS(x) 函數:返回 x 的絕對值

  • CEIL(x) 函數: 返回大於 x 的整數

  • MOD(x,y),對 x 和 y 進行取模操做

  • ROUND(x,y) 返回 x 四捨五入後保留 y 位小數的值;若是是整數,那麼 y 位就是 0 ;若是不指定 y ,那麼 y 默認也是 0 。

  • FLOOR(x) : 返回小於 x 的最大整數,用法與 CEIL 相反

  • TRUNCATE(x,y): 返回數字 x 截斷爲 y 位小數的結果, TRUNCATE 知識截斷,並非四捨五入。

  • RAND() :返回 0 到 1 的隨機值

日期和時間函數

日期和時間函數也是 MySQL 中很是重要的一部分,下面咱們就來一塊兒認識一下這些函數

函數 功能
NOW 返回當前的日期和時間
WEEK 返回一年中的第幾周
YEAR 返回日期的年份
HOUR 返回小時值
MINUTE 返回分鐘值
MONTHNAME 返回月份名
CURDATE 返回當前日期
CURTIME 返回當前時間
UNIX_TIMESTAMP 返回日期 UNIX 時間戳
DATE_FORMAT 返回按照字符串格式化的日期
FROM_UNIXTIME 返回 UNIX 時間戳的日期值
DATE_ADD 返回日期時間 + 上一個時間間隔
DATEDIFF 返回起始時間和結束時間之間的天數

下面結合示例來說解一下每一個函數的使用

  • NOW(): 返回當前的日期和時間

  • WEEK(DATE) 和 YEAR(DATE) :前者返回的是一年中的第幾周,後者返回的是給定日期的哪一年

  • HOUR(time) 和 MINUTE(time) : 返回給定時間的小時,後者返回給定時間的分鐘

  • MONTHNAME(date) 函數:返回 date 的英文月份

  • CURDATE() 函數:返回當前日期,只包含年月日

  • CURTIME() 函數:返回當前時間,只包含時分秒

  • UNIX_TIMESTAMP(date) : 返回 UNIX 的時間戳

  • FROM_UNIXTIME(date) : 返回 UNIXTIME 時間戳的日期值,和 UNIX_TIMESTAMP 相反

  • DATE_FORMAT(date,fmt) 函數:按照字符串 fmt 對 date 進行格式化,格式化後按照指定日期格式顯示

具體的日期格式能夠參考這篇文章 blog.csdn.net/weixin_3870…

咱們演示一下將當前日期顯示爲年月日的這種形式,使用的日期格式是 %M %D %Y

  • DATE_ADD(date, interval, expr type) 函數:返回與所給日期 date 相差 interval 時間段的日期

interval 表示間隔類型的關鍵字,expr 是表達式,這個表達式對應後面的類型,type 是間隔類型,MySQL 提供了 13 種時間間隔類型

表達式類型 描述 格式
YEAR YY
MONTH MM
DAY DD
HOUR 小時 hh
MINUTE mm
SECOND ss
YEAR_MONTH 年和月 YY-MM
DAY_HOUR 日和小時 DD hh
DAY_MINUTE 日和分鐘 DD hh : mm
DAY_SECOND 日和秒 DD hh :mm :ss
HOUR_MINUTE 小時和分 hh:mm
HOUR_SECOND 小時和秒 hh:ss
MINUTE_SECOND 分鐘和秒 mm:ss
  • DATE_DIFF(date1, date2) 用來計算兩個日期之間相差的天數

查看離 2021 - 01 - 01 還有多少天

流程函數

流程函數也是很經常使用的一類函數,用戶可使用這類函數在 SQL 中實現條件選擇。這樣作可以提升查詢效率。下表列出了這些流程函數

函數 功能
IF(value,t f) 若是 value 是真,返回 t;不然返回 f
IFNULL(value1,value2) 若是 value1 不爲 NULL,返回 value1,不然返回 value2。
CASE WHEN[value1] THEN[result1] ...ELSE[default] END 若是 value1 是真,返回 result1,不然返回 default
CASE[expr] WHEN[value1] THEN [result1]... ELSE[default] END 若是 expr 等於 value1, 返回 result1, 不然返回 default

其餘函數

除了咱們介紹過的字符串函數、日期和時間函數、流程函數,還有一些函數並不屬於上面三類函數,它們是

函數 功能
VERSION 返回當前數據庫的版本
DATABASE 返回當前數據庫名
USER 返回當前登錄用戶名
PASSWORD 返回字符串的加密版本
MD5 返回 MD5 值
INET_ATON(IP) 返回 IP 地址的數字表示
INET_NTOA(num) 返回數字表明的 IP 地址

下面來看一下具體的使用

  • VERSION: 返回當前數據庫版本

  • DATABASE: 返回當前的數據庫名

  • USER : 返回當前登陸用戶名

  • PASSWORD(str) : 返回字符串的加密版本,例如

  • MD5(str) 函數:返回字符串 str 的 MD5 值

  • INET_ATON(IP): 返回 IP 的網絡字節序列

  • INET_NTOA(num)函數:返回網絡字節序列表明的 IP 地址,與 INET_ATON 相對

總結

這篇文章我帶你手把手擼了一波 MySQL 的高級內容,其實說高級也不必定真的高級或者說難,其實就是區分不一樣梯度的東西。

你的支持就是我擼文的動力!我是 cxuan,咱們下篇文章見。

另外,添加個人微信 becomecxuan,加入每日一題羣,天天一道面試題分享,更多內容請參見個人 Github,成爲最好的 bestJavaer

我本身肝了六本 PDF,微信搜索 程序員cxuan 關注公衆號後,在後臺回覆 cxuan ,領取所有 PDF,這些 PDF 以下

六本 PDF 連接

相關文章
相關標籤/搜索