之前兩篇文章帶你了解了 MySQL 的基礎語法和 MySQL 的進階內容,那么這篇文章我們來了解一下 MySQL 中的高級內容。
其他文章:
138 張圖帶你 MySQL 入門
47 張圖帶你 MySQL 進階!!!
本文思維導圖如下。
事務控制和鎖定語句
我們知道,MyISAM 和 MEMORY 存儲引擎支持表級鎖定(table-level locking),InnoDB 存儲引擎支持行級鎖定(row-level locking),BDB 存儲引擎支持頁級鎖定(page-level locking)。各個鎖定級別的特點如下
頁級鎖:銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般
表級鎖:表級鎖是對整張表進行加鎖,MyISAM 和 MEMORY 主要支持表級鎖,表級鎖加鎖快,不會出現死鎖,鎖的粒度比較粗,并發度最低
行級鎖:行級鎖可以說是 MySQL 中粒度最細的一種鎖了,InnoDB 支持行級鎖,行級鎖容易發生死鎖,并發度比較好,同時鎖的開銷也比較大。
MySQL 默認情況下支持表級鎖定和行級鎖定。但是在某些情況下需要手動控制事務以確保整個事務的完整性,下面我們就來探討一下事務控制。但是在探討事務控制之前我們先來認識一下兩個鎖定語句
鎖定語句
MySQL 的鎖定語句主要有兩個 Lock 和 unLock,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_TABLES 和 NO_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_DATE 和 NO_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 BY 和 WITH 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 的高級內容,其實說高級也不一定真的高級或者說難,其實就是區分不同梯度的東西。
原文標題:炸裂!MySQL 82 張圖帶你飛
文章出處:【微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。
責任編輯:haq
-
MySQL
+關注
關注
1文章
821瀏覽量
26651
原文標題:炸裂!MySQL 82 張圖帶你飛
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論