我的MYSQL學習心得(6) : 函式

發表於2015-06-03

這一節主要介紹MYSQL裡的函式,MYSQL裡的函式很多,我這裡主要介紹MYSQL裡有而SQLSERVER沒有的函式

數學函式

1、求餘函式MOD(X,Y)

MOD(X,Y)返回x被y除後的餘數,MOD()對於帶有小數部分的數值也起作用,他返回除法運算後的精確餘數

2、四捨五入函式TRUNCATE(X,Y)

TRUNCATE(X,Y)返回被捨去至小數點後y位的數字x。若y的值為0,則結果不帶有小數點或不帶有小數部分。

若y設為負數,則截去(歸零)x小數點左邊起第y位開始後面所有低位的值。

TRUNCATE(1.32,1)保留小數點後一位數字,返回值為1.3

TIPS:ROUND(X,Y)函式在擷取值的時候會四捨五入,而TRUNCATE(x,y)直接擷取值,並不進行四捨五入

3、求餘函式HEX(X)和UNHEX(X)函式

有以下的程式碼可以演示HEX和UNHEX的功能:

查詢的結果為:746869732069732061207465737420737472

查詢的結果為:this is a test str


字串函式

計算字串字元數的函式

1、CHAR_LENGTH(STR)返回值為字串str所包含的字元個數。一個多位元組字元算作一個單字元

2、合併字串函式CONCAT_WS(x,s1,s2,……)

CONCAT_WS(x,s1,s2,……),CONCAT_WS代表CONCAT with Separator,是CONCAT()函式的特殊形式。

第一個引數x是其他引數的分隔符,分隔符的位置放在要連線的兩個字串之間。分隔符可以是一個字串,也可以是

其他引數。如果分隔符為NULL,則結果為NULL。函式會忽略任何分隔符引數後的NULL值。

CONCAT_WS(‘-‘,’1st’,’2nd’,’3rd’)使用分隔符‘-’將3個字串連線成一個字串,結果為“1st-2nd-3rd”;

CONCAT_WS(‘-‘,’1st’,NULL,’3rd’)因為第二個值為NULL,所以第二個值不會出現在結果裡

3、替換字串的函式INSERT(S1,X,LEN,S2)

INSERT(S1,X,LEN,S2)函式跟SQLSERVER裡的STUFF()函式的功能是一樣的,這裡不作介紹了

4、填充字串的函式LPAD(S1,LEN,S2)和RPAD(S1,LEN,S2)

LPAD(S1,LEN,S2)返回字串s1,其左邊由字串s2填補到len字串長度。假如s1的長度大於len,則返回值被縮短至len字元。

LPAD()函式和RPAD()函式功能跟SQLSERVER裡的 REPLACE()相似,不過功能更加強大

字串“hello”長度大於4,不需要填充,因此LPAD(‘hello’,4,’??’)只返回被縮短的長度為4的子串

字串“hello”長度小於10,LPAD(‘hello’,10,’??’)返回結果為“?????hello”,左側填充“?”,長度為10

5、RPAD(S1,LEN,S2)返回字串s1,其右邊被字串s2填補至len字元長度。假如字串s1的長度大於len,則返回值被縮短到len字元長度

字串“hello”長度大於4,不需要填充,因此RPAD(‘hello’,4,’?’)只返回被縮短的長度為4的子串”hell”

6、刪除空格的函式TRIM(S)

TRIM(S)刪除字串s兩側的空格

MYSQL這裡比SQLSERVER方便,SQLSERVER要刪除兩邊的空格,需要使用: SELECT LTRIM(RTRIM(‘ hello ‘))

刪除指定字串的函式TRIM(S1 FROM S)

7、TRIM(S1 FROM S)刪除字串s中兩端所有的子字串s1。s1為可選項,在未指定情況下,刪除空格

‘xyxboxyokxxyxy’兩端的重複字串“xy”,而中間的“xy”並不刪除,結果為

8、重複生成字串的函式REPEAT(S,N)

這個函式跟SQLSERVER裡的REPLICATE()函式是一樣的,引數個數都是一樣的,這裡不作介紹了

9、比較字串大小的函式STRCMP(S1,S2)

STRCMP(S1,S2)若所有的字串均相同,則返回0;若根據當前分類次序,第一個引數小於第二個,則返回-1,其他情況返回1

“txt”小於“txt2”,因此 STRCMP(‘txt’,’txt2′) 返回結果為-1

STRCMP(‘txt2′,’txt’)返回結果為1

“txt”與“txt”相等,因此STRCMP(‘txt’,’txt’)返回結果為0

10、匹配子串開始位置的函式

LOCATE(STR1,STR)、POSITION(STR1 IN STR)、INSTR(STR,STR1)3個函式作用相同,返回子字串str1在字串str中的開始位置

這三個函式跟SQLSERVER裡的CHARINDEX()函式功能類似

子字串“ball”在字串“football”中從第5個字母位置開始,因此3個函式返回結果都為5

11、返回指定位置的字串的函式

ELT(N,字串1,字串2,字串3,…,),若N=1,則返回值為字串1,若N=2,則返回值為字串2,以此類推。

若N小於1或大於引數的數目,則返回值為NULL

由結果可以看到,ELT(3,’1st’,’2nd’,’3rd’)返回第3個位置的字串“3rd”;指定返回字串位置超出引數個數,返回NULL

12、返回指定字串位置的函式FIELD(S,S1,S2,…)

FIELD(S,S1,S2,…)返回字串s在列表s1,s2,……中第一次出現的位置,在找不到s的情況下,返回值為0。

如果s為NULL,則返回值為0,原因是NULL不能同任何值進行同等比較。

FIELD(‘hi’,’hihi’,’hey’,’hi’,’bas’)函式中字串hi出現在列表的第3個字串位置,因此返回結果為3

FIELD(‘hi’,’hihi’,’lo’,’hilo’,’foo’) 列表中沒有字串hi,因此返回結果為0

13、返回子串位置的函式FIND_IN_SET(S1,S2)

FIND_IN_SET(S1,S2)返回字串s1在字串列表s2中出現的位置,字串列表是一個由多個逗號

‘,’分開的字串組成的列表。如果s1不在s2或s2為空字串,則返回值為0。如果任意一個引數為NULL,則返回值為NULL。

這個函式在第一個引數包含一個逗號‘,’時將無法正常執行。

雖然FIND_IN_SET(S1,S2)和FIELD(S,S1,S2,…)兩個函式格式不同,但作用類似,都可以返回指定字串在字串列表中的位置

14、選取字串的函式MAKE_SET(X,S1,S2,…)

MAKE_SET(X,S1,S2,…)返回由x的二進位制數指定的相應位的字串組成的字串,s1對應位元1,s2對應位元01以此類推。

s1,s2…中的NULL值不會被新增到結果中。

1的二進位制值為0001,4的二進位制值為0100,1與4進行異或操作之後的二進位制值為0101,從右到左第一位和第三位為1。

MAKE_SET(1,’a’,’b’,’c’)返回第一個字串

MAKE_SET(1|4,’hello’,’nice’,’world’) 返回從左端開始第一和第三個字串組成的字串


日期和時間函式

1、獲取當前日期的函式和獲取當前時間的函式

CURDATE()、CURRENT_DATE()、CURRENT_TIMESTAMP()、LOCALTIME()、NOW()、SYSDATE()

以上函式都是返回當前日期和時間值,MYSQL的函式數量的確比SQLSERVER多很多,SQLSERVER獲取當前時間和日期用的

函式是: SELECT GETDATE()

返回UTC日期的函式和返回UTC時間的函式

MYSQL裡返回UTC日期和時間是分開的,而SQLSERVER裡是一起的

MYSQL

2、獲取月份的函式MONTHNAME(DATE)

MONTHNAME(DATE)函式返回日期date對應月份的英文全名

返回8月份的英文

3、獲取季度、分鐘和秒鐘的函式

QUARTER(DATE)返回date對應的一年中的季度值,範圍是從1~4

使用QUARTER(DATE)函式返回指定日期對應的季度

4月份在第二季度,所以返回2

4、MINUTE(TIME)返回time對應的分鐘數,範圍是從0~59

返回10分鐘

5、SECOND(time) 返回time對應的秒數,範圍是從0~59

返回10秒

6、獲取日期的指定值的函式EXTRACT(type FROM date)

EXTRACT(type FROM date)這個函式跟SQLSERVER裡的DATEPART()函式是一樣的

獲取日期中的年份

SQLSERVER

MYSQL

7、時間和秒鐘轉換的函式

TIME_TO_SEC(time)返回已轉化為秒的time引數,轉換公式為:小時*3600+分鐘*60+秒

SEC_TO_TIME(second)函式可以將秒轉換為小時、分鐘和秒數的second引數值

SEC_TO_TIME(second)函式和TIME_TO_SEC(time)函式互為反函式

8、計算日期和時間的函式

MYSQL裡計算日期和時間的函式比較多

增加日期:DATE_ADD(date,interval  expr type),ADDDATE(date,interval  expr type)

減去日期:DATE_SUB(date,interval  expr type),SUBDATE(date,interval  expr type)

增加時間:ADD_TIME(date,expr)

減去時間:SUBTIME(date,expr)

時間差:DATEDIFF()

日期和時間格式化:

DATE_FORMAT(date,format)

TIME_FORMAT(time,format)

返回日期時間字串的顯示格式:GET_FORMAT(val_type,format_type)

相對來說,SQLSERVER在時間日期方面的計算就沒有那麼多函式了

基本上SQLSERVER利用下面兩個函式來通殺日期時間計算的場景


條件判斷函式

條件判斷函式也稱為流程控制函式,根據滿足的條件的不同,執行相應的流程。

MYSQL中進行條件判斷的函式有IF、IFNULL、CASE

雖然SQLSERVER裡也有IF和CASE,不過MYSQL裡的IF語句的語法跟SQLERVER有很大出入

1、IF(expr,v1,v2)函式

IF(expr,v1,v2)如果表示式expr是TRUE(expr<>0 and expr<>NULL),則IF()的返回值為v1;

否則返回值為v2。IF()的返回值為數字值或字串值,具體情況視其所在語境而定

1>2的結果為FALSE,IF(1>2,2,3)返回第二個表示式的值3。

TIPS:如果v1或v2中只有一個明確是NULL,則IF()函式的結果型別為非NULL表示式的結果型別。

2、IFNULL(V1,V2)函式

IFNULL(V1,V2)假如v1不為NULL,則IFNULL(V1,V2)的返回值為v1;否則其返回值為v2。

IFNULL()的返回值是數字或是字串,具體情況視語境而定

IFNULL(1,2)雖然第二個值也不為空,但返回結果依然是第一個值;

IFNULL(NULL,10)第一個值為空,因此返回“10”

注意:IFNULL(V1,V2)函式跟SQLSERVER裡的 SELECT NULLIF() 函式不一樣

SQLSERVER裡的NULLIF函式

需要兩個引數,如果兩個指定的表示式等價,則返回null

例子:NULLIF(a,b)

說明:如果a和b是相等的,那麼返回NULL,如果不相等返回a

select NULLIF(‘eqeqweqwe’,’1′) 結果是eqeqweqwe

select NULLIF(1,1) 結果是NULL

a和b的型別要一致

3、CASE函式

注意:一個CASE表示式的預設返回值型別是任何返回值的相容集合型別,但具體情況視其所在語境而定。

如果用字串語境中,則返回結果為字串。如果用在數字語境中,則返回結果為十進位制、實數值或整數值

這個資料型別在拼接SQL語句的時候特別容易忽略,有時候會在拼接SQL語句的時候,case 後面的表示式或者when後面的表示式不一致報錯!

參考文章:http://support.microsoft.com/kb/969467/zh-cn

修補程式: 錯誤訊息,當您執行查詢時,SQL Server 2008年中使用 CASE 函式:”轉換失敗時轉換為資料型別 < Type2 > < Type1 > 值 < 值 >”

在MSDN論壇也有一個相關的帖子,大概是因為拼接sql的時候case 後面的表示式值的資料型別和else後面的表示式值的資料型別不一致導致拼接sql失敗

具體的帖子地址忘記了,也找不到,如果找到以後會補充上


系統資訊函式

1、獲取MYSQL版本號、連線數和資料庫名的函式

VERSION()返回指示MYSQL伺服器版本的字串。這個字串使用utf8字符集

2、CONNECTION_ID()返回MYSQL伺服器當前連線的次數,每個連線都有各自唯一的ID

檢視當前使用者的連線數

這裡返回1,返回值根據登入的次數會有不同。

3、SHOW PROCESSLIST;

4、SHOW FULL PROCESSLIST;

processlist命令的輸出結果顯示了有哪些執行緒在執行,不僅可以檢視當前所有的連線數,還可以檢視當前的連線狀態

幫助識別出有問題的查詢語句等。

如果是root帳號,能看到所有使用者的當前連線。如果是其他普通帳號,則只能看到自己佔用的連線。showprocesslist只能列出當前100條

如果想全部列出,可以使用SHOW FULL PROCESSLIST命令

show full processlist會看到連線使用的記憶體

show processlist

show full processlist

各個列的含義

(1)id列,使用者登入mysql時,系統分配的“connection_id”

(2)user列,顯示當前使用者。如果不是root,這個命令就只顯示使用者許可權範圍的sql語句

(3)host列,顯示這個語句是從哪個ip的哪個埠上發的,可以用來跟蹤出現問題語句的使用者

(4)db列,顯示這個程式目前連線的是哪個資料庫

(5)command列,顯示當前連線的執行的命令,一般取值為休眠(sleep),查詢(query),連線(connect)

(6)time列,顯示這個狀態持續的時間,單位是秒

(7)state列,顯示使用當前連線的sql語句的狀態,很重要的列,後續會有所有狀態的描述,state只是語句執行中的某一個狀態。一個sql語句,

以查詢為例

可能需要經過

copying to tmp table,

sorting result,

sending data

等狀態才可以完成

(8)info列,顯示這個sql語句,是判斷問題語句的一個重要依據。

5、DATABASE()和SCHEMA()函式返回使用utf8字符集的預設(當前)資料庫名

可以看到,兩個函式的作用相同

6、獲取使用者名稱的函式

USER()、CURRENT_USER()、CURRENT_USER、SYSTEM_USER()、SESSION_USER()

這幾個函式返回當前被MYSQL伺服器驗證的使用者名稱和主機名組合。這個值符合確定當前登入使用者

存取許可權的MYSQL帳戶。一般情況下,這幾個函式的返回值是相同的。

返回結果指示了當前帳戶連線伺服器的使用者名稱以及所連線的客戶主機,root為當前登入的使用者名稱,localhost為登入的主機名

7、獲取字串的字符集和排序方式的函式

CHARSET(STR)返回字串str自變數的字符集

CHARSET(‘abc’)返回系統預設的字符集utf8;

CHARSET(CONVERT(‘abc’ USING latin1))返回的字符集為latin1;

VERSION()返回的字串使用utf8字符集,因此CHARSET返回結果為utf8

8、COLLATION(str)返回字串str的字元排列方式

可以看到,使用不同字符集時字串的排列方式不同

9、獲取最後一個自動生成的ID值的函式

LAST_INSERT_ID()自動返回最後一個INSERT或UPDATE為AUTO_INCREMENT列設定的第一個發生的值

(1)一次插入一條記錄

首先建立表worker,其ID欄位帶有AUTO_INCREMENT約束

分別單獨向表worker插入2條記錄

檢視已經插入的資料可以發現,最後一條插入的記錄的ID欄位值為2,使用LAST_INSERT_ID()檢視最後自動生成的ID值

可以看到,一次插入一條記錄時,返回值為最後一條插入記錄的ID值

(2)一次同時插入多條記錄

接下來,向表中插入多條記錄

查詢已經插入的記錄

可以看到最後一條記錄的ID欄位值為5,使用LAST_INSERT_ID()檢視最後自動生成的ID值

結果顯示,ID欄位值不是5而是3,這是為什麼呢?

在向資料表插入一條記錄時,LAST_INSERT_ID()返回帶有AUTO_INCREMENT約束的欄位最新生成的值2;繼續向表

中同時新增3條記錄,這時候因為當使用一條INSERT語句插入多個行時,LAST_INSERT_ID只返回插入的第一行資料

時產生的值,在這裡為第3條記錄。之所以這樣,是因為這使依靠其他伺服器複製同樣的INSERT語句變得簡單

TIPS:LAST_INSERT_ID是與table無關的,如果向表a插入資料後,再向表b插入資料,LAST_INSERT_ID返回表b中的ID值

這裡跟SQLSERVER不一樣

使用下面指令碼來測試,無論使用方式一還是方式二,當前的LAST_INSERT_ID都是最後一個值


加密函式

1、加密函式PASSWORD(STR)

PASSWORD(STR)從原文密碼str計算並返回加密後的密碼字串,當引數為NULL時,返回NULL

MYSQL將PASSWORD函式加密後的密碼儲存到使用者許可權表中

TIPS:PASSWOR()函式在MYSQL伺服器的鑑定系統中使用;不應將他用在個人應用程式中,PASSWORD()函式加密是單向的(不可逆)

PASSWORD執行密碼加密與UNIX中密碼加密方式不同

2、加密函式MD5(str)

MD5(str)為字串算出一個MD5 128位元校驗和。該值以32位十六進位制數字的二進位制字串形式返回,若引數為NULL,則會返回NULL

3、加密函式ENCODE(str,pswd_str)

ENCODE(str,pswd_str)使用pswd_str作為密碼,加密str。使用DECODE()解密結果,結果是一個和str長度相同的二進位制字串

可以看到加密後的結果為亂碼

4、解密函式DECODE(crypt_str,pswd_str)

DECODE(crypt_str,pswd_str)使用pswd_str作為密碼,解密加密字串crypt_str,crypt_str是由ENCODE()返回的字串

可以看到,解密出來的字串

ENCODE()和DECODE互為反函式


其他函式

1、格式化函式FORMAT(x,n)

FORMAT(x,n)將數字x格式化,並以四捨五入的方式保留小數點後n位,結果以字串的形式返回。

若n為0,則返回結果函式不含小數部分

FORMAT(12332.123465,4)保留4位小數點值,並進行四捨五入,結果為12,332.1235

2、不同進位制的數字轉換的函式

CONV(N,from_base,to_base)函式進行不同進位制數間的轉換。

CONV(‘a’,16,2)將十六進位制的a轉換為二進位制表示的數值。

3、IP地址與數字相互轉換的函式

INET_ATON(expr)給出一個作為字串的網路地址的點地址表示,返回一個代表該地址數值的整數。

地址可以是4或8位元地址

INET_NTOA(expr)給定一個數字網路地址(4或8位元),返回作為字串的該地址的點地址表示。

4、加鎖函式和解鎖函式

GET_LOCK(str,timeout)設法使用字串str給定的名字得到一個鎖,超時為timeout秒。

RELEASE_LOCK(str)解開被GET_LOCK()獲取的,用字串str所命名的鎖。

IS_FREE_LOCK(str)檢查名為str的鎖是否可以使用

IS_USED_LOCK(str)檢查名為str的鎖是否正在被使用

5、重複執行指定操作的函式

BENCHMARK(count,expr)函式重複count次執行表示式expr。他可以用於計算MYSQL處理表示式的速度。

結果值通常為0(0只是表示處理過程很快,並不是沒有花費時間)

另一個作用是他可以在MYSQL客戶端內部報告語句執行的時間。

首先,使用PASSWORD函式加密密碼

可以看到PASSWORD()函式執行花費的時間為0.00098秒

下面使用BENCHMARK函式重複執行PASSWORD操作500000次

由此可以看出,使用BENCHMARK執行500000次的時間為0.49690秒,明顯比執行一次的時間延長了。

TIPS:BENCHMARK報告的時間是客戶端經過的時間,而不是在伺服器端的CPU時間,每次執行後報告的時間並不一定是相同的。

6、改變字符集的函式

CONVERT(…using…)帶有USING的CONVERT()函式被用來在不同的字符集之間轉化資料。

預設為utf8字符集,通過CONVERT()將字串“string”的預設字符集改為latin1

7、改變資料型別的函式

CAST(x,AS type)和CONVERT(x,type)函式將一個型別的值轉換為另一個型別的值,可轉換的type有:

BINARY、CHAR(n)、DATE、TIME、DATETIME、DECIMAL、SIGNED、UNSIGNED

在SQLSERVER裡也是使用這兩個函式進行資料型別轉換的~

可以看到, CAST(100 AS CHAR(2))將整數資料100轉換為帶有2個顯示寬度的字串型別,結果為10

CONVERT(‘2013-8-9 12:12:12’,TIME)將DATETIME型別的值,轉換為TIME型別值,結果為“12:12:12”


總結 

這一節簡單介紹了MYSQL裡的一些函式,並且比較了與SQLSERVER的區別

TIPS:

1、MYSQL中,日期時間以字串形式儲存在資料表中,因此可以使用字串函式分別擷取日期時間值的不同部分

2、修改預設的字符集,更改MYSQL預設的字符集,在Windows中,只需要修改my.ini,該檔案在MYSQL安裝目錄下。

修改配置檔案中的default-character-set和character-set-server引數值,將其改為想要的字符集名稱,如:

gbk、gb2312、latin1等,修改完之後,重啟MYSQL服務,即可生效。

如果不確定當前使用的字符集,可以使用下面的SQL語句來檢視當前字符集進行對比

如有不對的地方,歡迎大家拍磚o(∩_∩)o 

2014-7-17函式補充

http://baike.baidu.com/link?url=uwjXFFHv_ZzkloAoUMdSCTJd7xTCZwRw41w885eqwyskXUuH5jmQQPKaLZGE_IoSOmXJqZXbcKnXjB1FtKEt7K

相關文章