存儲過程框架
DEMILITER $$ -- 重定義符
DROP PROCEDURE IF EXISTS store_procedure$$ -- 如果存在此名的存儲過程,先刪除
CREATE PROCEDURE store_procedure() -- 創建名為store_procedure的存儲過程
BEGIN -- 開始
-- 內容
END$$ -- 結束
DEMILITER ; -- 恢復;為分隔符
在使用復合語句時,必須考慮和解決這樣一個問題:復合語句塊里的語句必須以分號(;)彼此隔開,但因為分號同時也是mysql程序默認使用的語句分隔符,所以在使用mysql程序定義存儲程序時會發生沖突。解決這個問題的辦法是使用DELIMITER命令把mysql程序的語句分隔符重定義為另一個字符或字符串。
注釋:
兩個連字符加一個空格的單行注釋,如:-- 注釋
類似C語言的多行注釋,如:/*注釋
*/
變量:
變量聲明:
DECLARE 變量名;
示例:DECLARE my_integer INT;
變量聲明同時初始化:
DECLARE 變量名 DEFAULT 變量初始化值;
示例:DECLARE my_integer INT DEFAULT 0;
變量賦值:
SET 變量名=值;
示例:SET my_integer=1;
常用的MySQL數據類型
數據類型 |
解釋 |
相應值的示例 |
INT, INTEGER |
32位整數。取值范圍為-21億到+21億,如果是非符號數,值可以達到42億,但這樣做就不能包括負數 |
123,345 -2,000,000,000 |
BIGINT |
64位整數。取值范圍為-9萬億到+9萬億或者非負的0到18萬億 |
9,000,000,000,000,000,000 -9,000,000,000,000,000,000 |
FLOAT |
32位浮點數。取值范圍為1.7e38 to 1.7e38或者非負的0到3.4e38 |
0.00000000000002 17897.890790 -345.8908770 1.7e21 |
DOUBLE |
64位浮點數。取值范圍接近無限(1.7e308) |
1.765e203 -1.765e100 |
DECIMAL(precision,scale) NUMERIC(precision,scale) |
定點數。存儲情況取決於precision,能保存可能出現的數字范圍。 NUMERIC通常用來保存重要的十進制數,例如現金 |
78979.00 -87.50 9.95 |
DATE |
日期類型,沒有詳述時間 |
'1999-12-31' |
DATETIME |
日期和時間,時間精確到秒 |
'1999-12-31 23:59:59' |
CHAR(length) |
定長字符串。值會被空白填充至制定長度,最大長度為255字節 |
'hello world ' |
VARCHAR(length) |
最大長度為64K的可變字符串 |
'Hello world' |
BLOB, TEXT |
最大64K長度,BLOB用來保存2進制數據,TEXT用來保存文本數據 |
任何能想象的內容 |
LONGBLOB, LONGTEXT |
BLOB和TEXT的加長版本,存儲能力達4GB |
任何能想象的內容,但比BLOB和TEXT能存放更大的長度 |
用戶變量(全局變量):
可以跨存儲過程使用;
DECALRE @g_variable INT DEFAULT 0;
參數:
參數類型分為輸入(IN,默認)、輸出(OUT)、輸入輸出(INOUT)三種類型;
存儲函數只能用輸入(IN)模式,但可以有一個返回值,對於需要返回多個值的功能,只能采用存儲過程;
示例:存儲過程計算平方根
DEMILITER $$
DROP PROCEDURE sqrt_store_procedure
CREATE PROCEDURE sqrt_store_procedure(IN in_num INT, OUT out_num FLOAT)
BEGIN
SET out_num=SQRT(in_num);
END$$
DEMILITER ;
操作符:
數學操作符
操作符 |
描述 |
用例 |
+ |
加 |
SET var1=2+2; à 4 |
- |
減 |
SET var2=3-2; à 1 |
* |
乘 |
SET var3=3*2; à 6 |
/ |
除 |
SET var4=10/3; à 3.3333 |
DIV |
整除 |
SET var5=10 DIV à3; 3 |
% |
模 |
SET var6=10%3; à 1 |
比較操作符
操作符 |
描述 |
示例 |
示例結果 |
> |
是否大於 |
1>2 |
False |
< |
是否小於 |
2<1 |
False |
<= |
是否小於等於 |
2<=2 |
True |
>= |
是否大於等於 |
3>=2 |
True |
BETWEEN |
是否位於兩個值之間 |
5 BETWEEN 1 AND 10 |
True |
NOT BETWEEN |
是否不位於兩個值之間 |
5 NOT BETWEEN 1 AND 10 |
False |
IN |
值位於列表中 |
5 IN (1,2,3,4) |
False |
NOT IN |
值不位於列表中 |
5 NOT IN (1,2,3,4) |
True |
= |
等於 |
2=3 |
False |
<>, != |
不等於 |
2<>3 |
False |
<=> |
Null安全等於(如果兩個值均為Null返回TRUE) |
NULL<=>NULL |
True |
LIKE |
匹配簡單模式 |
"Guy Harrison" LIKE "Guy%" |
True |
REGEXP |
匹配擴展正則表達式 |
"Guy Harrison" REGEXP "[Gg]reg" |
False |
IS NULL |
值為空 |
0 IS NULL |
False |
IS NOT NULL |
值不為空 |
0 IS NOT NULL |
True |
邏輯操作符
AND操作符比較兩個邏輯表達式,並且只在兩個表達式都為真是才返回TRUE。
AND |
TRUE |
FALSE |
NULL |
TRUE |
TRUE |
FALSE |
NULL |
FALSE |
FALSE |
FALSE |
NULL |
NULL |
NULL |
NULL |
NULL |
OR操作符比對兩個邏輯表達式,並且只要其中的一個表達式為真即返回TRUE。
OR |
TRUE |
FALSE |
NULL |
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
TRUE |
FALSE |
NULL |
NULL |
TRUE |
NULL |
NULL |
XOR操作符只有在兩個值不完全為真時才返回TRUE。
XOR |
TRUE |
FALSE |
NULL |
TRUE |
FALSE |
TRUE |
NULL |
FALSE |
TRUE |
FALSE |
NULL |
NULL |
NULL |
NULL |
NULL |
位操作符
操作符 |
用途 |
| |
OR |
& |
AND |
<< |
Shift bits to left |
>> |
Shift bits to right |
~ |
NOT or invert bits |
條件執行:
IF、CASE;
示例:IF
DECLARE count INT DEFAULT 0;
IF (price > 100) THEN
count = 0;
ELSEIF (prict >= 30 AND prict <= 100) THEN
count=1;
ELSE
count=2;
END IF;
示例:CASE
DECLARE count INT DEFAULT 0;
CASE enum_type
WHEN ‘A’ THEN
count=1;
WHEN ‘B’ THEN
count=2;
ELSE -- 未滿足’A’、’B’的情況下,執行ELSE流程
count=3;
END CASE;
在沒有ELSE的情況下,如果enum_type沒有’A’、’B’的情況,會拋出一個異常:ERROR 1339 (20000): Case not found for CASE statement
CASE語句中的WHEN表達式也可以是條件,如:
CASE price
WHEN (price > 200) THEN
count=1;
WHEN ((price > 100) AND (price <= 200)) THEN
count=2;
ELSE
count=3;
END CASE;
循環:
簡單循環LOOP、END LOOP;
當條件為真時,繼續執行的循環WHILE、END WHILE;
循環直至條件為真:REPEAT、UNTIL;
三種循環都可以用LEAVE子句來終止循環;
示例:LOOP
DECLARE count INT DEFAULT 0;
my_loop: LOOP
SET count=count+1;
IF (count=10)
LEAVE my_loop;
END IF;
SELECT CONCAT(count, “ is select value”);
END LOOP my_loop;
SELECT “I can count to 10”;
ITERATE語句用來重新從循環頭部開始執行,而不執行任何在循環中遺留下來的語句。
DECLARE count INT DEFAULT 0;
my_loop: LOOP
SET count=count+1;
IF (count=10)
LEAVE my_loop;
ELSEIF (MOD(count,2)=0)
ITERATE my_loop;
END IF;
SELECT CONCAT(count, “ is select value”);
END LOOP my_loop;
SELECT “I can count to 10 odd num”;
REPEAT……UNTIL循環,REPEAT循環的循環體總是能確保至少運行一次。
DECLARE count INT DEFAULT 0;
my_loop: REPEAT
SET count=count+1;
IF (MOD(count,2)<>0)
SELECT CONCAT(count, “ is select value”);
END IF;
UNTIL count=10
END LOOP my_loop;
SELECT “I can count to 10 odd num”;
WHILE循環,WHILE循環只有在條件為真是才執行循環。
DECLARE count INT DEFAULT 0;
my_loop: WHILE (couunt<10) DO
SET count=count+1;
IF (MOD(count,2)<>0)
SELECT CONCAT(count, “ is select value”);
END IF;
END WHILE my_loop;
SELECT “I can count to 10 odd num”;
MYSql函數:
字符串函數
這些函數主要對字符串變量執行操作,比方說:你可以連接字符串,在字符串中查找字符,得到子串和其他常規操作。
數學函數
這些函數主要對數字進行操作,比方說:你可以進行乘方(平方),三角函數(sin,cos),隨機數函數和對數函數等。
日期和時間函數
折現函數主要的操作對象是日期和時間,比方說:你可以得到當前時間,從一個日期上加上或減去一個時間間隔,找出兩個日期間的差異,獲取某個確定的時間點(比如:得到一天中某時間的小時數)。
其它函數
這些函數包括了所有不容易被分入上面類別中函數。他們包括類型轉換函數,流程控制函數(比如:CASE),信息反饋函數(比如服務器版本)和加密函數。
經常被使用的MySQL函數
函數 |
描述 |
ABS(number) |
返回提供數字的絕對值。比方說, ABS(-2.3)=2.3. |
CEILING(number) |
返回下一個最大整數,比方說, CEILING(2.3)=3. |
CONCAT(string1[,string2,string3,...]) |
返回所有提供字符串的連接形式的值 |
CURDATE |
返回當前時間(不帶時間) |
DATE_ADD(date,INTERVAL amount_type) |
給提供的時間值加上一個時間間隔並返回一個新時間。正確的形式有SECOND, MINUTE, HOUR, DAY, MONTH和YEAR |
DATE_SUB(date,INTERVAL interval_type) |
從提供的時間值上減去一個時間間隔並返回一個新的時間。正確的形式有SECOND, MINUTE, HOUR, DAY, MONTH和YEAR |
FORMAT(number,decimals) |
返回一個指定精確度的數值,並給與以1000為單位的分割(通常使用“,”) |
GREATEST(num1,num2[,num3, ... ]) |
返回所有提供參數中的最大數 |
IF(test, value1,value2) |
測試一個邏輯條件,如果為真則返回value1,如果為假返回value2 |
IFNULL(value,value2) |
返回第一個值,除非第一個值為空;這樣的話返回第二個值 |
INSERT(string,position,length,new) |
把一個字符串插入到另一個字符串中 |
INSTR(string,substring) |
返回一個字符串中子串的位置 |
ISNULL(expression) |
如果參數為空則返回1,否則返回0 |
LEAST(num1,num2[,num3, ... ]) |
返回參數列表中的最小值 |
LEFT(string,length) |
返回字符串最左邊的部分 |
LENGTH(string) |
返回字符串中的字節數。CHAR_LENGTH可以被用來返回字符數(這會在你使用多字節字符集是產生差異) |
LOCATE(substring,string[,number]) |
返回字符串中子串的位置,可選的第三個參數為在父字符串中開始搜索的位置 |
LOWER(string) |
返回給定字符串的小寫形式 |
LPAD(string,length,padding) |
返回字符串 str, 其左邊由字符串padding 填補到length 字符長度,第三個參數為填充字符 |
LTRIM(string) |
刪除所有字符串中的前綴空格 |
MOD(num1,num2) |
返回第一個數除於第二個數后的模(余數部分) |
NOW |
返回當前日期和時間 |
POWER(num1,num2) |
返回num1的num2次方 |
RAND([seed]) |
返回一個隨機數。seed可被用於隨機數生成器的種子數 |
REPEAT(string,number) |
返回一個重復number次string的字符串 |
REPLACE(string,old,new) |
用new替換所有出現old的地方 |
ROUND(number[,decimal]) |
舍去給定數值的指定精度的位數 |
RPAD(string,length,padding) |
返回字符串 str, 其右邊由字符串padding 填補到length 字符長度,第三個參數為填充字符 |
RTRIM(string) |
刪除字符串尾部的空格 |
SIGN(number) |
如果number小於0則返回-1,如果大於0則返回1,如果為0則返回0 |
SQRT(number) |
返回number的平方根 |
STRCMP(string1,string2) |
如果兩個值相同則返回0,若根據當前分類次序,第一個參數小於第二個,則返回 -1,其它情況返回 1 。 |
SUBSTRING(string,position,length) |
從字符串指定位置開始返回length個字符 |
UPPER(string) |
將指定字符串轉換為大寫 |
VERSION |
返回MySQL服務器當前版本號的字符串 |
和數據庫交互:
將一個SQL語句所返回的單個記錄放入本地變量中;
創建一個“游標”來迭代SQL語句所返回的結果集;
執行一個SQL語句,將執行后的結果集返回給它的調用程序;
內嵌一個不返回結果集的SQL語句,如INSERT,UPDATA,DELETE等;
將一個SQL語句所返回的單個記錄放入本地變量中:SELECT INTO
示例:
DECLARE num INT;
SELECT NUM(price)
INTO num
FROM tabprice;
SELECT CONCAT(“Total Price is”, num);
游標
游標的聲明必須在我們所有的變量聲明之后。在的變量之前定義游標會產生一個1337錯誤。游標總是和SELECT語句配合使用。
DECLARE cur CURSOR FOR SELECT * FROM customers;
創建一個“游標”來迭代SQL語句所返回的結果集:CURSOR
查詢多條記錄數據;
示例:CURSOR
DECLARE done DEFAULT -1;
DECLARE nprice DEFAULT 0;
DECLARE cur1 CURSOR FOR
SELECT price FROM tabprice;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果沒有記錄,錯誤處理no data to fetch條件,幾乎所有的游標都要用到
SET done=0;
OPEN cur1;
my_loop: LOOP
FETCH cur1 INTO nprice; -- 循環從游標中取值
IF (done=1)
LEAVE my_loop;
END IF;
END LOOP my_loop;
CLOSE cur1;
DEALLOCATE cur1; -- 釋放游標
不使用no data to fetch的另一種解決方案@@FETCH_STATUS
@@fetch_status是MSSQL的一個全局變量
其值有以下三種,分別表示三種不同含義:【返回類型integer】
0 FETCH 語句成功
-1 FETCH 語句失敗或此行不在結果集中
-2 被提取的行不存在
@@fetch_status值的改變是通過fetch next from實現的
“FETCH NEXT FROM Cursor”
DECLARE Employee_Cursor CURSOR FOR
SELECT LastName, FirstName FROM Northwind.dbo.Employees
OPEN Employee_Cursor
FETCH NEXT FROM Employee_Cursor
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM Employee_Cursor
END
CLOSE Employee_Cursor
DEALLOCATE Employee_Cursor
No data to fetch條件捕獲在嵌套游標循環中使用比較復雜,有兩種方案
1.在內循環結束時重置條件為0
DECLARE done DEFAULT -1;
DECLARE nprice DEFAULT 0;
DECLARE cur1 CURSOR FOR
SELECT price FROM tabprice;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果沒有記錄,錯誤處理no data to fetch條件,幾乎所有的游標都要用到
SET done=0;
OPEN cur1;
my_loop: LOOP
FETCH cur1 INTO nprice; -- 循環從游標中取值
DECLARE cur2 CURSOR FOR SELECT * FROM cumtomers;
OPEN cur2;
my_loop2: LOOP
FETCH cur2 INTO custom;
IF (done=1)
LEAVE my_loop2;
END IF;
END LOOP my_loop2;
CLOSE cur2;
DEALLOCATE cur2; -- 釋放游標
SET done=0; -- 重置事件值
IF (done=1)
LEAVE my_loop;
END IF;
END LOOP my_loop;
CLOSE cur1;
DEALLOCATE cur1; -- 釋放游標
2.內循環封閉為一個塊
DECLARE done DEFAULT -1;
DECLARE nprice DEFAULT 0;
DECLARE cur1 CURSOR FOR
SELECT price FROM tabprice;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果沒有記錄,錯誤處理no data to fetch條件,幾乎所有的游標都要用到
SET done=0;
OPEN cur1;
my_loop: LOOP
FETCH cur1 INTO nprice; -- 循環從游標中取值
cur2begin: BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=1;
DECLARE cur2 CURSOR FOR SELECT * FROM cumtomers;
OPEN cur2;
my_loop2: LOOP
FETCH cur2 INTO custom;
IF (done2=1)
LEAVE my_loop2;
END IF;
END LOOP my_loop2;
CLOSE cur2;
DEALLOCATE cur2; -- 釋放游標
END cur2begin;
IF (done=1)
LEAVE my_loop;
END IF;
END LOOP my_loop;
CLOSE cur1;
DEALLOCATE cur1; -- 釋放游標
在存儲過程中調用另一個存儲過程:
CALL 存儲過程名;
存儲函數:
函數的參數列表中模式只能為IN。OUT和INOUT參數不被允許。制定IN關鍵字是被允許也是缺省的;
函數必須返回一個值,它的類型被定義於函數的頭部;
函數能被SQL語句所調用;
函數可能不返回任何結果集;
在程序的真正目的是比對值和需要返回值時或者你希望在SQL語句中創建用戶自定義函數的時候更多的考慮使用存儲函數,而不是存儲過程;
框架:
DEMILITER $$ -- 重定義符
DROP FUNCTION IF EXISTS store_function$$ -- 如果存在此名的存儲函數,先刪除
CREATE FUNCTION store_function() RETURNS INT DETERMINITISTIC
-- 創建名為store_procedure的存儲函數
--
MySQL相較於存儲過程,對於存儲函數有更嚴格的規則。函數必須聲明不修改SQL(使用NO SQL或者READS SQL DATA子句)或者聲明為DETERMINISTIC(如果服務器被允許開啟二進制日志)。這個限制是為了防止當函數返回不確定值時,數據庫同步復制的不一致性,我們的樣例例程使用了“deterministic”,這樣我們就能確保在提供了相同的參數的情況下返回相同的值 |
BEGIN -- 開始
-- 內容
RETURN(返回值);
END$$ -- 結束
DEMILITER ; -- 恢復;為分隔符