MySQL 存儲過程學習筆記


 

存儲過程框架

 

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 

 

 

 

 

 

條件執行:

 

IFCASE

 

示例: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;

 

 

 

循環:

 

簡單循環LOOPEND LOOP

 

當條件為真時,繼續執行的循環WHILEEND WHILE

 

循環直至條件為真:REPEATUNTIL

 

三種循環都可以用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語句,如INSERTUPDATADELETE等;

 

將一個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_statusMSSQL的一個全局變量

 

其值有以下三種,分別表示三種不同含義:【返回類型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 ; -- 恢復;為分隔符

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM