MySQL在5.0以前並不支持存儲過程,這使得MySQL在應用上大打折扣。MySQL 5.0終於開始支持存儲過程了。
MySQL的關鍵字大小寫通用。該學習筆記對關鍵字使用大寫;變量名,表名使用小寫。
注釋
MySQL存儲過程可使用兩種風格的注釋。
- 雙模杠:--注釋內容 一般用於單行注釋。
- c風格:/* 注釋內容 */ 一般用於多行注釋。
理解DELIMITER聲明分割符
DELIMITER是分割符的意思。
DELIMITER 符號 -- 表示設置某個符號為分隔符。
通常程序中經常出現
- DELIMITER //
- DELIMITER ;
MySQL默認以“;”為分隔符,若沒有聲明分割符,那么編譯器會把存儲過程當成SQL語句進行處理,則存儲過程的編譯過程會報錯,所以要事先用DELIMITER關鍵字申明當前段分隔符,這樣MySQL才會將“;”當做存儲過程中的代碼,不會執行這些代碼,用完了之后要把分隔符還原。
創建存儲過程
MySQL存儲過程創建的格式:
CREATE PROCEDURE 過程名 ([過程參數[,...]]) [特性 ...] 過程體
例:一個簡單的存儲過程。使用參數s輸出查詢結果。
DELIMITER // CREATE PROCEDURE proc1(OUT s int) BEGIN SELECT COUNT(*) INTO s FROM user; END // DELIMITER ;
這里有一個輸出參數s,類型是int型,如果有多個參數用","分割開。
存儲過程輸入輸出參數
MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型IN、OUT、INOUT。
CREATE PROCEDURE([[IN |OUT |INOUT ] 參數名 數據類形...])
- IN 輸入參數:表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值。
- OUT 輸出參數:該值可在存儲過程內部被改變,並可返回。
- INOUT 輸入輸出參數:調用時指定,並且可被改變和返回。
例:IN參數示例。
DELIMITER // CREATE PROCEDURE demo_in_parameter(IN p_in int) BEGIN SELECT p_in; SET p_in=2; SELECT p_in; END; // DELIMITER ;
執行調用:
SET @p_in=1; CALL demo_in_parameter(@p_in);
+------+
| p_in |
+------+
| 1 |
+------+
+------+
| p_in |
+------+
| 2 |
+------+
SELECT @p_in;
+-------+
| @p_in |
+-------+
| 1 |
+-------+
以上可以看出,p_in雖然在存儲過程中被修改,但並不影響@p_id的值
例:OUT參數示例
DELIMITER // CREATE PROCEDURE demo_out_parameter(OUT p_out int) BEGIN SELECT p_out; SET p_out=2; SELECT p_out; END; // DELIMITER ;
執行調用:
SET @p_out=1; CALL sp_demo_out_parameter(@p_out);
+-------+
| p_out |
+-------+
| NULL |
+-------+
+-------+
| p_out |
+-------+
| 2 |
+-------+
SELECT @p_out;
+-------+
| p_out |
+-------+
| 2 |
+-------+
例:INOUT參數示例。
DELIMITER // CREATE PROCEDURE demo_inout_parameter(INOUT p_inout int) BEGIN SELECT p_inout; SET p_inout=2; SELECT p_inout; END; // DELIMITER ;
執行調用:
SET @p_inout=1; CALL demo_inout_parameter(@p_inout) ;
+---------+
| p_inout |
+---------+
| 1 |
+---------+
+---------+
| p_inout |
+---------+
| 2 |
+---------+
SELECT @p_inout;
+----------+
| @p_inout |
+----------+
| 2 |
+----------+
過程體
過程執行的開始與結束使用BEGIN與END進行標識。
BEGIN 執行語句 END
過程體允許嵌套使用。
變量
變量定義
DECLARE 變量名類型 DEFAULT 值; DECLARE 變量名1,變量名2 類型 DEFAULT 值; DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
其中,datatype為MySQL的數據類型,如:int, float, date, varchar(length)。
例如:
DECLARE x, y INT DEFAULT 0 DECLARE l_int int unsigned DEFAULT 4000000; DECLARE l_numeric number(8,2) DEFAULT 9.95; DECLARE l_date date DEFAULT '1999-12-31'; DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59'; DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';
變量賦值
可以看到進行賦值時候需要在前面加上:SET 這個關鍵字。
SET 變量名 = 表達式值 [,variable_name = expression ...]
例:
DECLARE total_count INT DEFAULT 0 SET total_count = 10;
當然由於存儲過程的特殊性(用於數據庫的數據操作),所以除了SET這種賦值方法,還可以通過SELECT INTO語句將返回的值賦給變量:
DECLARE total_products INT DEFAULT 0 SELECT COUNT(*) INTO total_products FROM products
變量的Scope(作用范圍)
會話變量(session variable),也叫做用戶定義的變量(user defined variable)。在變量名稱前面加上“@”符號,代表整個會話過程他都是有作用的,類似於去全局變量。
會話變量用途比較廣,因為只要在一個會話內(就是某個應用的一個連接過程中),這個變量可以在被調用的存儲過程或者代碼之間共享數據。
參看以下示例,以理解這種變量和本地變量的區別:
例:在MySQL客戶端使用用戶變量
SELECT 'Hello World' into @x; SELECT @x;
+-------------+
| @x |
+-------------+
| Hello World |
+-------------+
SET @y='Goodbye Cruel World'; SELECT @y;
+---------------------+
| @y |
+---------------------+
| Goodbye Cruel World |
+---------------------+
SET @z=1+2+3; SELECT @z;
+------+
| @z |
+------+
| 6 |
+------+
例:在存儲過程中使用用戶變量
CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World'); SET @greeting='Hello'; CALL GreetWorld();
+----------------------------+
| CONCAT(@greeting,' World') |
+----------------------------+
| Hello World |
+----------------------------+
例:在存儲過程間傳遞全局范圍的用戶變量
CREATE PROCEDURE p1() SET @last_procedure='p1'; CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc);
CALL p1(); CALL p2();
+-----------------------------------------------+
| CONCAT('Last procedure was ',@last_proc |
+-----------------------------------------------+
| Last procedure was p1 |
+-----------------------------------------------+
注意:
1.用戶變量名一般以@開頭。
2.濫用用戶變量會導致程序難以理解及管理。
調用MySQL存儲過程
用call和過程名以及一個括號,括號里面為參數。具體的調用方法可以參看上面的例子。
MySQL存儲過程是否存在的查詢
我們像知道一個數據庫下面有那些表,我們一般采用show tables;進行查看。那么我們要查看某個數據庫下面的存儲過程,是否也可以采用呢?答案是,我們可以查看某個數據庫下面的存儲過程,但是是令一鍾方式。
可以用
select name from mysql.proc where db='數據庫名';
或者
select routine_name from information_schema.routines where routine_schema='數據庫名';
或者
SHOW procedure status where db='數據庫名';
若需要查看某個存儲過程的詳細,使用如下方法:
SHOW CREATE PROCEDURE 數據庫.存儲過程名;
MySQL存儲過程的修改
ALTER PROCEDURE
更改用CREATE PROCEDURE 建立的預先指定的存儲過程,其不會影響相關存儲過程或存儲功能。
MySQL存儲過程的刪除
刪除一個存儲過程比較簡單,和刪除表一樣:
DROP PROCEDURE
從MySQL的表格中刪除一個或多個存儲過程。
存儲過程若存在則刪除
DELIMITER // DROP PROCEDURE IF EXISTS updateContactValidForEmployeeLeaveJob // CREATE PROCEDURE updateContactValidForEmployeeLeaveJob() READS SQL DATA BEGIN DECLARE done INT DEFAULT 0; DECLARE employee_id INT; DECLARE employee_csr CURSOR FOR SELECT id FROM employee WHERE valid=0; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; OPEN employee_csr; cursor_loop:LOOP IF done=1 THEN LEAVE cursor_loop; END IF; FETCH employee_csr into employee_id; UPDATE contact SET valid= 0 WHERE belong_id=employee_id AND `type`='internal'; END LOOP cursor_loop; CLOSE employee_csr; END; // DELIMITER ;
MySQL存儲過程的控制語句
變量作用域
內部的變量在其作用域范圍內享有更高的優先權,當執行到end。變量時,內部變量消失,此時已經在其作用域外,變量不再可見了,應為在存儲過程外再也不能找到這個申明的變量,但是可以通過out參數或者將其值指派。
DELIMITER // CREATE PROCEDURE proc3() begin declare x1 varchar(5) default 'outer'; begin declare x1 varchar(5) default 'inner'; select x1; end; select x1; end; // DELIMITER ;
條件語句
if語句
IF expression THEN commands [ELSEIF expression THEN commands] [ELSE commands] END IF;
例:
DELIMITER // CREATE PROCEDURE proc2(IN parameter int) begin declare var int; set var=parameter+1; if var=0 then insert into t values(17); end if; if parameter=0 then update t set s1=s1+1; else update t set s1=s1+2; end if; end; // DELIMITER ;
switch語句
同編程里面的switch ....case.....類似,使用CASE同編程一樣也是當判斷比較多時便於閱讀和維護,我們也來看下CASE的語法:
CASE case_expression WHEN when_expression THEN commands WHEN when_expression THEN commands ... ELSE commands END CASE;
例:
DELIMITER // CREATE PROCEDURE proc3 (in parameter int) begin declare var int; set var=parameter+1; case var when 0 then insert into t values(17); when 1 then insert into t values(18); else insert into t values(19); end case; end; // DELIMITER ;
循環語句
while語句
WHILE的格式是這樣的:
WHILE expression DO 執行語句; END WHILE
例:
DELIMITER // CREATE PROCEDURE proc4() begin declare var int; set var=0; while var<6 do insert into t values(var); set var=var+1; end while; end; // DELIMITER ;
repeat語句
REPEAT的格式是這樣的:
REPEAT 執行語句; UNTIL expression END REPEAT
REPEAT和的do...while非常類似。它在執行操作后檢查結果,而while則是執行前進行檢查。
例:
DELIMITER // CREATE PROCEDURE proc5 ()
begin declare v int; set v=0; repeat insert into t values(v); set v=v+1; until v>=5 end repeat; end; // DELIMITER ;
loop語句
LOOP用來標記循環;而LEAVE表示離開循環;ITERATE則繼續循環。
DELIMITER $$ DROP PROCEDURE IF EXISTS `test`.`LoopProc` $$ CREATE PROCEDURE `test`.`LoopProc` () BEGIN DECLARE x INT; DECLARE str VARCHAR(255); SET x = 1; SET str = ''; loop_label: LOOP IF x > 10 THEN LEAVE loop_label; END IF; SET x = x + 1; IF (x mod 2) THEN ITERATE loop_label; ELSE SET str = CONCAT(str,x,','); END IF; END LOOP; SELECT str; END
$$ DELIMITER ;
以上代碼輸出10以內的偶數,用逗號分隔。這里注意到x>10的時候就LEAVE掉,如果遇到奇數則ITERATE,奇數對2取模為1,表示true
loop循環不需要初始條件,這點和while 循環相似,同時和repeat循環一樣不需要結束條件, leave語句的意義是離開循環。
例:
DELIMITER // CREATE PROCEDURE proc6 () begin declare v int; set v=0; LOOP_LABLE:loop insert into t values(v); set v=v+1; if v >=5 then leave LOOP_LABLE; end if; end loop; end; // DELIMITER ;
標號
標號可以用在begin repeat while 或者loop 語句前,語句標號只能在合法的語句前面使用。可以跳出循環,使運行指令達到復合語句的最后一步。
ITERATE迭代
ITERATE
通過引用復合語句的標號,來從新開始復合語句
例:
DELIMITER // CREATE PROCEDURE proc10 () begin declare v int; set v=0; LOOP_LABLE:loop if v=3 then set v=v+1; ITERATE LOOP_LABLE; end if; insert into t values(v); set v=v+1; if v>=5 then leave LOOP_LABLE; end if; end loop; end; // DELIMITER ;
游標(Cursor)
1、游標的作用及屬性
游標的作用就是用於對查詢數據庫所返回的記錄進行遍歷,以便進行相應的操作;游標有下面這些屬性:
a、游標是只讀的,也就是不能更新它;
b、游標只能在一個方向上進行遍歷,不能在記錄之間隨意進退,不能跳過某些記錄;
c、避免在已經打開游標的表上更新數據。
2、如何使用游標
使用游標需要遵循下面步驟:
a、用DECLARE語句聲明一個游標:
DECLARE cursor_name CURSOR FOR SELECT_statement;
上面這條語句就對,我們執行的select語句返回的記錄指定了一個游標。
b、使用OPEN語句來打開上面你定義的游標:
OPEN cursor_name;
c、用FETCH語句來獲得下一行數據,並且游標也將移動到對應的記錄:
FETCH cursor_name INTO variable list;
d、將游標釋放掉:
CLOSE cursor_name;
在使用游標時需要注意的是,使用定義一個針對NOT FOUND的條件處理函數(condition handler)來避免出現"no data to fetch"這樣的錯誤,條件處理函數就是當某種條件產生時所執行的代碼,這里但我們游標指到記錄的末尾時,便達到NOT FOUND這樣條件,這個時候我們希望繼續進行后面的操作,所以我們會在下面的代碼中看到一個CONTINUE。先看看我們的表格內容:
下面的游標使用演示獲取庫存量小於100的產品的代碼code,這個代碼純粹演示如何使用,在這里沒有其他任何意義。
DELIMITER $$ DROP PROCEDURE IF EXISTS `test`.`CursorProc` $$ CREATE PROCEDURE `test`.`CursorProc` () BEGIN DECLARE no_more_products, quantity_in_stock INT DEFAULT 0; DECLARE prd_code VARCHAR(255); DECLARE cur_product CURSOR FOR SELECT code FROM products; /*First: Delcare a cursor,首先這里對游標進行定義*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_products = 1; /*when "not found" occur,just continue,這個是個條件處理,針對NOT FOUND的條件*/ /* for loggging information 創建個臨時表格來保持*/ CREATE TEMPORARY TABLE infologs ( Id int(11) NOT NULL AUTO_INCREMENT, Msg varchar(255) NOT NULL, PRIMARY KEY (Id) ); OPEN cur_product; /*Second: Open the cursor 接着使用OPEN打開游標*/ FETCH cur_product INTO prd_code; /*Third: now you can Fetch the row 把第一行數據寫入變量中,游標也隨之指向了記錄的第一行*/ REPEAT SELECT quantity INTO quantity_in_stock FROM products WHERE code = prd_code; IF quantity_in_stock < 100 THEN INSERT INTO infologs(msg) VALUES (prd_code); END IF; FETCH cur_product INTO prd_code; UNTIL no_more_products = 1 END REPEAT; CLOSE cur_product; /*Finally: cursor need be closed 用完后記得用CLOSE把資源釋放掉*/ SELECT * FROM infologs; DROP TABLE infologs; END $$ DELIMITER ;
條件處理(Condition Handling) / 錯誤、異常處理
有時候,不希望存儲過程拋出錯誤中止執行,而是希望返回一個錯誤碼。
MySQL存儲過程支持異常處理,通過定義 CONTINUE/EXIT 異常處理的 HANDLER 來捕獲
SQLWARNING/NOT FOUND/SQLEXCEPTION (警告 / 無數據 / 其他異常)。
其中, FOR 后面可以改為 SQLWARNING, NOT FOUND, SQLEXCEPTION 來指示所有異常都處理,相當於 oracle 中的 others。
在游標里面我們有簡要的介紹了一個NOT FOUND這個條件處理(錯誤、異常處理)的情況,條件處理涉及到兩個語句,一個是DECLARE...CONDITION,另一個是DECLARE....HANDLER。在游標的例子中是使用了一個DECLARE....HANDLER。先來看看DECLARE....HANDLER。
DECLARE....HANDLER語句
這個語句用於但數據庫出現某種情況的時候(condition,大部分指發生某種錯誤時),來定義具體的處理辦法(handler);所以這里涉及到包括:a、就是個什么情況 b、如何處理它;下面是其格式
DECLARE handler_action HANDLER FOR condition_value [, condition_value] ... statement handler_action: CONTINUE | EXIT | UNDO condition_value: mysql_error_code | SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION
這里面需要注意幾點:
a、condition_value [,condition_value],這個的話說明可以包括多種情況(方括弧表示可選的),也就是一個handler可以定義成針對多種情況進行相應的操作;另外condition_value可以包括的值有上面列出來的6種:
1、mysql_error_code,這個表示mysql的錯誤代碼,錯誤代碼是一個數字,完成是由mysql自己定義的,這個值可以參考mysql數據庫錯誤代碼及信息。
2、SQLSTATE [VALUE] sqlstate_value,這個同錯誤代碼類似形成一一對應的關系,它是一個5個字符組成的字符串,關鍵的地方是它從ANSI SQL和ODBC這些標准中引用過來的,因此更加標准化,而不像上面的error_code完全是mysql自己定義給自己用的,這個和第一個類似也可以參考mysql數據庫錯誤代碼及信息。
3、condtion_name,這個是條件名稱,它使用DECLARE...CONDITION語句來定義,這個后面我們會介紹如何定義自己的condition_name。
4、SQLWARNING,表示SQLTATE中的字符串以'01'起始的那些錯誤,比如Error: 1311 SQLSTATE: 01000 (ER_SP_UNINIT_VAR)
5、NOT FOUND,表示SQLTATE中的字符串以'02'起始的那些錯誤,比如Error: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA),其實這個錯誤就是用在我們介紹游標的那個問題所出現的情況,也就是沒有fetch到記錄,也就是我們游標到記錄的尾巴了的情況。
6、SQLEXCEPTION,表示SQLSTATE中的字符串不是以'00'、'01'、'02' 起始的那些錯誤,這里'00'起始的SQLSTATE其實表示的是成功執行而不是錯誤,另外兩個就是上面的4和5的兩種情況。
上面的6種情況其實可以分為兩類,一類就是比較明確的處理,就是對指定的錯誤情況進行處理,包括1、2、3這三種方式;另一類是對對應類型的錯誤的處理,就是對某一群錯誤的處理,包括4、5、6這三種方式。這個是介紹了condition_value。另外還要注意的一個內容是MySQL在默認情況下(也就是我們沒有定義處理錯誤的方法-handler)自己的錯誤處理機制:1、對於SQLWARNING和NOT FOUND的處理方法就是無視錯誤繼續執行,所以在游標的例子里面如果我們沒有對repeat的條件判斷的那個值做個no_more_products=1的handler來處理,那么循環就會一直下去。2、對於SQLEXCEPTION的話,其默認的處理方法是在出現錯誤的地方就終止掉了。
b、statement,這個比較簡單就是當出現某種條件/錯誤時,我們要執行的語句,可以是簡單的如 SET var = value這樣的簡單的語句,也可以是復雜的多行的語句,多行的話可以使用BEGIN ..... END這里把語句包括在里面(這個好比delphi里面的情況,注意到我們的存儲過程也是多行的,所以也要BEGIN .... END)。
c、handler_action,這個表示當執行完上面的statement后,希望執行怎樣的動作,這里包括CONTINUE、EXIT、UNDO,表示繼續、退出、撤銷(暫時不支持)。這邊就是兩種動作,其實這兩種動作在上面也說過了,CONTINUE就是一個是SQLWARNING和NOT FOUND的默認處理方法,而EXIT就是SQLEXCEPTION的默認處理方法。
來看個簡單的例子,這里創建一個對SQLSTATE的代碼為'23000'的錯誤(重復的主鍵)進行處理的HANDLER,每次發生時對變量@x進行增加1:
DELIMITER $$ DROP PROCEDURE IF EXISTS `test`.`ConditionProc` $$ CREATE PROCEDURE `test`.`ConditionProc` () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x = @x+1; INSERT INTO products values(1,default,default,default,default,default); INSERT INTO products values(1,default,default,default,default,default); SELECT @x; END
$$ DELIMITER ;
代碼比較簡單,當然這里我們需要對數據庫進行一點修改,把除了主鍵外其他的字段設置了默認值,方便測試。
測試比較簡單,這里我們數據庫里面本身就有記錄了,然后在Qurey browser中先輸入。
SET @x = 0;
然后調用存儲過程下面是結果:
通過結果我們知道出現了兩次插入的記錄同原有的記錄出現主鍵重復的情況。當然這個是由下面這個代碼觸發的。
INSERT INTO products values(1,default,default,default,default,default);
2、DECLARE...CONDITION語句
這個語句其實是為了讓我們的錯誤條件更加的清晰明了化的,對於上面的情況,像SQLSTATE '23000'這種表示是一種很不直觀的方法,要通過相應的文檔去對應,閱讀起來比較不方便。而DECLARE....CONDITION可以對條件定義相對應的名稱,看個例子就清楚了:
DECLARE duplicate_key CONDITION FOR SQLSTATE '23000'; DECLARE CONTINUE HANDLER FOR duplicate_key BEGIN -- body of handler END;
當然在上面的例子沒有用到BEGIN....END,只有一行SET @x=@x+1;這里用duplicate_key這個條件名稱來對應到SQLSTATE '23000'上面,這樣查看起來更加的直觀。duplicate_key就是上面介紹DECLARE....HANDLER時候的那個condition_name。
MySql常用的比較函數和比較操作符
1、比較操作符:
= 、 >、 <、 >=、 <=、 <>、 != 、 <=>
- <> 和 != 意義是一樣的都是不等於的意思。
- <=> 是用於當比較的兩邊的值存在是空(NULL)的情況,這種情況有的時候會遇到,mysql提供這種方式的比較符,類似於"=",不同的是當兩邊要比較的數都為NULL的話它返回true(表示兩邊相等),如果其中有一邊是NULL的話它返回為false(表示兩邊不相等)。如果是使用"="比較操作符,當兩邊任何一邊有NULL的時候返回都是NULL。
2、比較函數:
(1)BETWEEN...AND :檢測某個數是不是在某個范圍內。 expr BETWEEN min AND max。對應的還有個NOT BETWEEN...AND,表示不再某個范圍
(2)IN() :檢測某個數是不是在某些數里面。 expr IN (value,...)。對應的是NOT IN(),表示不在列出的數里面
(3)INTERVAL(N,N1,N2,N3,...):返回N1、N2、.....中第一個比N大的索引,N1、N2...需要按大小排序號比如INTERVA(10,1,10,100,1000)這個函數返回2,100的索引為2
(4)GREATEST():返回一組數的最大值。
(5)LEAST():返回一組數的最小值。
(6)IS :同布爾值判斷,IS boolean_value ,這里需要注意的是boolean_value有三種 TRUE、 FALSE、 UNKNOWN,UNKNOWN對應於值為空的情況,比如NULL IS UNKNOWN則返回TRUE。同IS相反的是IS NOT,用法類似。
(7)IS NULL:判斷一個值是不是為空。在使用ODBC編程是這個IS NULL除了判斷是否為空以為還有兩個用途:
1、如果 sql_auto_is_null 這個Mysql系統變量設置為1(默認為1),當插入一個AUTO_INCREMENT自動生成的值(自增長的值,系統自動會生成)之后,可以通過下面一條語句來得到之前插入的記錄:
SELECT * FROM tbl_name WHERE auto_col IS NULL
這里tbl_name是表名稱,auto_col對應於自增長的列名。得到的記錄中那個自增長列所對應的值同我們調用LAST_INSERT_ID()得到的值是相同的。當然如果插入失敗則上面的SELECT沒有記錄返回,當然如果sql_auto_is_null被設置為0 false則也不行。
2、對應DATE或者DATETIME的數據格式對應的字段,並且字段設置為非空NOT NULL,可以通過IS NULL來查找"0000-00-00"這個特殊的日期,下面是代碼:
SELECT * FROM tbl_name WHERE date_column IS NULL
這個主要考慮到ODBC里面不支持"0000-00-00"的一個日期值。
同IS NULL對應的是IS NOT NULL,使用類似。
(8)STRCMP:比較兩個字符,返回為-1、0、1這三種值。
(9)LIKE:簡單的模式匹配,這個是常被用到的功能。通常我們知道"%"代表任意多個字符,另外"_"代表一個字符。先看看LIKE的格式:
expr LIKE pat [ESCAPE 'escape_char']
ESCAPE是指定轉義符號。默認的ESCAPE(轉義)符號是"\",如果需要使用"%"和"_",默認情況下可以用"\%"和"\_"來表示;如果需要查找"\n",則需要搜索"\\n",如果需要查找"\",則需要搜索"\\\\",因為這里有兩次的解析,一次是parser(文本黏貼器)生成的(就是如果expr里面有'\'符號則黏貼器會把它轉變為'\\'),一次是匹配的時候的(匹配的時候'\\\\'就變為'\\'了)。
pat可以是字符串、字符串表達式,或者列名稱。
LIKE也可以用在數字的表達式中,比如 10 LIKE '1%' 這個也是返回true。
另外要注意的是如果expr 或者 pat 中有一個是NULL那么 LIKE將會返回 NULL.
9.MySQL存儲過程的基本函數
(1).字符串類
CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //連接字串
INSTR (string ,substring ) //返回substring首次在string中出現的位置,不存在返回0
LCASE (string2 ) //轉換成小寫
LEFT (string2 ,length ) //從string2中的左邊起取length個字符
LENGTH (string ) //string長度
LOAD_FILE (file_name ) //從文件讀取內容
LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定開始位置
LPAD (string2 ,length ,pad ) //重復用pad加在string開頭,直到字串長度為length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重復count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str
RPAD (string2 ,length ,pad) //在str后用pad補充,直到長度為length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符比較兩字串大小,
SUBSTRING (str , position [,length ]) //從str的position開始,取length個字符,
注:mysql中處理字符串時,默認第一個字符下標為1,即參數position必須大於等於1
mysql> select substring('abcd',0,2);
+-----------------------+
| substring('abcd',0,2) |
+-----------------------+
+-----------------------+
1 row in set (0.00 sec)
mysql> select substring('abcd',1,2);
+-----------------------+
| substring('abcd',1,2) |
+-----------------------+
| ab |
+-----------------------+
1 row in set (0.02 sec)
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
UCASE (string2 ) //轉換成大寫
RIGHT(string2,length) //取string2最后length個字符
SPACE(count) //生成count個空格
(2).數學類
ABS (number2 ) //絕對值
BIN (decimal_number ) //十進制轉二進制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //進制轉換
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小數位數
HEX (DecimalNumber ) //轉十六進制
注:HEX()中可傳入字符串,則返回其ASC-11碼,如HEX('DEF')返回4142143
也可以傳入十進制整數,返回其十六進制編碼,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求余
POWER (number ,power ) //求指數
RAND([seed]) //隨機數
ROUND (number [,decimals ]) //四舍五入,decimals為小數位數]
注:返回類型並非均為整數,如:
(1)默認變為整形值
mysql> select round(1.23);
+-------------+
| round(1.23) |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)
mysql> select round(1.56);
+-------------+
| round(1.56) |
+-------------+
| 2 |
+-------------+
1 row in set (0.00 sec)
(2)可以設定小數位數,返回浮點型數據
mysql> select round(1.567,2);
+----------------+
| round(1.567,2) |
+----------------+
| 1.57 |
+----------------+
1 row in set (0.00 sec)
SIGN (number2 ) //
(3).日期時間類
ADDTIME (date2 ,time_interval ) //將time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //轉換時區
CURRENT_DATE ( ) //當前日期
CURRENT_TIME ( ) //當前時間
CURRENT_TIMESTAMP ( ) //當前時間戳
DATE (datetime ) //返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或時間
DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式顯示datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上減去一個時間
DATEDIFF (date1 ,date2 ) //兩個日期差
DAY (date ) //返回日期的天
DAYNAME (date ) //英文星期
DAYOFWEEK (date ) //星期(1-7) ,1為星期天
DAYOFYEAR (date ) //一年中的第幾天
EXTRACT (interval_name FROM date ) //從date中提取日期的指定部分
MAKEDATE (year ,day ) //給出年及年中的第幾天,生成日期串
MAKETIME (hour ,minute ,second ) //生成時間串
MONTHNAME (date ) //英文月份名
NOW ( ) //當前時間
SEC_TO_TIME (seconds ) //秒數轉成時間
STR_TO_DATE (string ,format ) //字串轉成時間,以format格式顯示
TIMEDIFF (datetime1 ,datetime2 ) //兩個時間差
TIME_TO_SEC (time ) //時間轉秒數]
WEEK (date_time [,start_of_week ]) //第幾周
YEAR (datetime ) //年份
DAYOFMONTH(datetime) //月的第幾天
HOUR(datetime) //小時