何爲存儲過程?
存儲過程是一種可以反覆調用的數據庫程序。
存儲過程是爲了完成特殊的計算,經編譯保存在數據庫中,用戶指定存儲過程的名字並給定參數來調用執行,存儲過程實際上就是sql語言層面上的封裝與重用。
優點
- 有助於提高程序性能。 當創建存儲過程時 ,編譯後被保存在數據庫中。但mysql實現的存儲過程不同 ,MySQL的存儲過程按需編譯,編譯之後放在緩存中。MySQL爲存儲過程提供高速緩存
- 存儲過程有助於減少應用程序和數據庫中的流量
- 存儲的過程對任何應用都是可重用的和透明的。
- 存儲的過程是安全的。
缺點
- 大量存儲過程會使得內存增加,CPU的使用率可能也會飆升
- 存儲過程的構造使開發具有業務邏輯的存儲過程變的更加困難
- 存儲過程難以調試
- 開發和維護存儲過程並不容易
存儲過程語法
創建存儲過程
DELIMITER
與存儲過程語法無關
DELIMITER //
CREATE PROCEDURE getAllProducts()
BEGIN
SELECT * FROM test.comment_target;
END
DELIMITER ;
使用存儲過程
調用存儲過程
call getAllProducts
drop
存儲過程
DROP procedure IF EXISTS `getAllProducts`;
聲明變量
DECLARE v_name varchar(22) DEFAULT 'default_value';
變量類型,Mysql變量如INT,VARCHAR,DATETIME
也可DEFAULT NULL
DECLARE a,b INT(22) DEFAULT NULL;
SET a=1;
SELECT COUNT(*) INTO total_products FROM products;
存儲過程參數
IN
參數
CREATE PROCEDURE getAllProducts(IN productCode varchar(22))
BEGIN
SELECT * FROM test.comment_target where p_code= productCode ;
END
調用
call getAllProducts('1100');
OUT
參數
CREATE PROCEDURE CountByStatus( IN orderStatus VARCHAR(25), OUT total INT)
BEGIN
SELECT count(*)
INTO total
FROM comment_target WHERE score_target>0;
END
調用
call CountByStatus('shipped',@total);
select @total;
INOUT
參數
CREATE PROCEDURE setCount(INOUT count INT(4),IN inc INT(4))
BEGIN
SET count = count + inc;
END
調用
SET @count=1;
CALL setCount(@count,1);
CALL setCount(@count,3);
CALL setCount(@count,4);
SELECT @count;
存儲過程返回多個參數
即多個out參數,此處不演示
存儲過程IF
語法
IF
語法
IF expression THEN
statements;
END IF;
IF-ELSE
語法
IF expression THEN
statements;
ELSE
else-statements;
END IF;
IF ELSEIF ELSE
語法
IF expression THEN
statements;
ELSEIF elseif-expression THEN
elseif-statements;
...
ELSE
else-statements;
END IF;
存儲過程CASE
語法
CASE case_expression
WHEN when_expression_1 THEN commands
WHEN when_expression_2 THEN commands
...
ELSE commands
END CASE;
存儲過程中的MySQL循環
- WHILE循環
WHILE expression DO
statements
END WHILE
注意: 需要初始化值,否則容易死循環
- REPEAT循環
REPEAT
statements;
UNTIL expression
END REPEAT
注意:UNTIL
語句後沒有;
3. LOOP
,LEAVE
和ITERATE
語句
LEAVE
用於退出循環,類似break
ITERATE
用於跳過當前循環進行下一個,類似continue
LOOP
用於反覆執行某個代碼塊
例如:
CREATE PROCEDURE testLoop()
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;
MySQL遊標
要處理存儲過程中的結果集,則需要使用遊標。
遊標的作用:迭代查詢返回的一組行,並相應處理每一行,遊標爲只讀
- 只讀:無法通過光標更新基礎表中的數據。
- 不可滾動:只能按照SELECT語句確定的順序獲取行。不能以相反的順序獲取行。 此外,不能跳過行或跳轉到結果集中的特定行。
- 敏感:有兩種遊標:敏感遊標和不敏感遊標。敏感遊標指向實際數據,不敏感遊標使用數據的臨時副本。敏感遊標比一個不敏感的遊標執行得更快,因爲它不需要臨時拷貝數據。但是,對其他連接的數據所做的任何更改都將影響由敏感遊標使用的數據,因此,如果不更新敏感遊標所使用的數據,則更安全。 MySQL遊標是敏感的。
語法:
DECLARE cursor_name CURSOR FOR SELECT_statement;
遊標聲明必須在變量之後,遊標必須始終與Select
語句關聯
使用OPEN語句打開遊標。OPEN語句初始化遊標的結果集,因此您必須在從結果集中提取行之前調用OPEN語句。
OPEN cursor_name INTO variables list;
FETCH
檢索光標指向下一行,並將光標移動到結果集中的下一行
FETCH cursor_name INTO variables list;
關閉遊標
CLOSE cursor_name ;
使用MySQL遊標時,還必須聲明一個NOT FOUND處理程序來處理當遊標找不到任何行時的情況。 因爲每次調用FETCH語句時,遊標會嘗試讀取結果集中的下一行。
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;