MySQL存儲過程編程時一個復雜的主題,我們將在本章中為你提供完成基本任務的內容,其中包括:
1、怎樣創建存儲過程
2、存儲過程怎樣進行輸入輸出
3、怎樣和數據庫交互
4、怎樣用MySQL存儲編程語言創建過程,函數和觸發器
第一個存儲過程實例:
delimiter $$ drop procedure if exists HelloWorld$$ create procedure HelloWorld() begin select "Hello World"; end $$ 變量
本地變量可以用declare語句進行聲明。變量名稱必須遵循MySQL的列明規則,並且可以使MySQL內建的任何數據類型。你可以用default字句給變量一個初始值,並且可以用SET語句給變量賦一個新值
delimiter $$ drop procedure if exists variable_demo$$ begin declare my_integer int; declare my_big_integer bigint; declare my_currency numeric(8, 2); declare my_pi float default 3.1415926; declare my_text text; declare my_dob date default '1960-06-21'; declare my_varchar varchar(30) default "Hello World!"; set my_integer = 20; set my_big_integer = power(my_integer, 3); end $$ delimiter;
參數可以使我們的存儲程序更為靈活,更為實用。參數包括IN(只讀模式), INOUT(可讀寫模式)和OUT(只寫模式)。IN模式作為缺省的參數模式。
IN:任何對於該參數的修改都不會返回給調用它的程序
OUT:這個模式意味著存儲過程可以對參數賦值(修改參數的值),並且這個被修改的值會被返回給它的調用程序
INOUT:這個模式意味著存儲過程即可讀取傳入的參數,而且任何對於該參數的修改對於它的調用程序而言都是可見的
對於存儲函數而言,只能使用IN模式
delimiter $$ drop procedure if exists my_sqrt$$ create procedure my_sqrt(input_number int, out out_number float) begin set out_number = SQRT(input_number); end $$ delimiter;創建和執行使用OUT參數的存儲過程
call my_sqrt(12, @out_value) $$ select @out_value $$ 條件執行
通過購買量的多少來計算出貼現率的存儲程序,購買量超過$500可以返回20%,購買量超過$100可以返回10%。
delimiter $$ drop procedure if exists discounted_price$$ create procedure discounted_price(normal_price NUMERIC(8, 2), out discount_price NUMBERIC(8, 2)) begin if (normal_price > 500) then set discount_price = normal_price*.8; else if (normal_price > 100) then set discount_price = normal_price*.9; else set discount_price = normal_price; end if; end$$ delimiter; 循環
MySQL存儲程序語言提供了三種類型的循環
使用LOOP和END LOOP字句的簡單循環
當循環條件為真時繼續執行的循環,使用WHILE和END WHILE字句
循環直至條件為真,使用REPEAT和UNTIL字句
在這三種循環中,你都可以使用LEAVE字句來終止循環
DELIMITER $$ DROP PROCEDURE IF EXISTS simple_loop$$ CREATE PROCEDURE simple_loop() BEGIN DECLARE counter INT DEFAULT 0; my_simple_loop: LOOP SET counter = counter 1; IF counter = 10 THEN LEAVE my_simple_loop; END IF; END IF; END LOOP my_simple_loop; select "I can count to 10"; END$$ DELIMITER; 錯誤處理
1、如果你認為內嵌的SQL語句會返回空記錄,或者你想用游標捕獲SELECT語句所返回的記錄,那麼一個NO FOUND 錯誤處理可以防止存儲過程過早的被終止
2、如果你認為SQL語句可能返回錯誤(比如違背約束條件),你可以創建一個錯誤處理來阻止程序終止。這個處理將代替你的默認錯誤處理並繼續程序的執行。
和數據庫交互
大多數存儲過程包含了各種和數據庫表的交互,它們包括四種主要的交互:
1、將一個SQL語句所返回的單個記錄放入本地變量中。
2、創建一個“游標”來迭代SQL語句所返回的結果集
3、執行一個SQL語句,將執行後的結果集返回給它的調用程序
4、內嵌一個不反悔結果集的SQL語句,如INSERT,UPDATE, DELETE等
對本地變量使用SELECT INTO
當需要在單個記錄數據中獲取查詢信息,你就可以使用SELECT INTO 語法(無論是使用單個記錄,多個記錄的混合數據,還是多個表連接)。在這種情況下,你可以再SELECT語句中跟隨一個INTO子句,告訴MySQL得到的查詢數據返回給誰
DELIMITER $$ DROP PROCEDURE IF EXISTS customer_sales $$ CREATE PROCEDURE customer_sales(int_customer_id INT) READS SQL DATA BEGIN DECLARE total_sales NUMERIC(8, 2); SELECT SUM(sale_value) INTO total_sales FROM sales WHERE customer_id = in_customer_id; SELECT CONCAT('Total sales for ', in_customer_id, 'is', 'total_sales'); END; $$
使用游標
SELECT INTO 定義了單記錄查詢,但是很多應用程序要求查詢多記錄數據,你可以使用MySQL中的游標來實現這一切,游標允許你將一個或更多的SQL結果集放進存儲程序變量中,通常用來執行結果集中各個單記錄的處理。
DELIMITER $$ DROP PROCEDURE cursor_example() READ SQL DATA BEGIN DECLARE l_employee_id INT; DECLARE l_salary NUMERIC(8, 2); DECLARE l_department_id INT; DECLARE done INT DEFAULT 0; DECLARE curl CURSOR FOR SELECT employee_id, salary, department_id FROM employees; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN curl; emp_loop : LOOP FETCH curl INTO l_employee_id, l_salary, l_department_id; IF done = 1 THEN LEAVE emp_loop; END IF; END LOOP emp_loop;CLOSE curl;