MySQL中Procedure事務編寫基礎筆記

目錄:mysql

1、PROCEDURE;sql

2、CREATE PROCEDURE基本語法;數據庫

3、PROCEDURE小進階安全

  3.一、基本的DECLARE語句;服務器

  3.二、聲明HANDLER句柄;ide

  3.三、聲明CURSOR遊標;函數

  3.四、循環語句;學習

4、順帶提一下觸發器TRIGGER編碼

1、PROCEDURE:

PROCEDURE,事務,一個存儲過程,實際上就是在服務器端直接在數據庫中編寫一段代碼做運算,在服務器端進行高效的運算,運算結果直接返還給客戶端。spa

它和FUNCTION一個明顯的不一樣點是,FUNCTION最後會有RETURN語句,返回運算結果,PROCEDURE不容許有RETURN語句的,可是能夠在參數表中指定返還數據。

PROCEDURE編譯完成後會存儲在數據庫中,須要調用的時候使用CALL語句對事務或者函數進行調用。編寫PROCEDURE不只能夠避免重複編碼,同時還能夠提升計算效率。

2、CREATE PROCEDURE基本語法:

下面不妨先看一看CREATE PROCEDURE以及CREATE FUNCTION的語法:

 1 CREATE
 2     [DEFINER = { user | CURRENT_USER }]
 3     PROCEDURE sp_name ([proc_parameter[,...]])
 4     [characteristic ...] routine_body
 5 CREATE
 6     [DEFINER = { user | CURRENT_USER }]
 7     FUNCTION sp_name ([func_parameter[,...]])
 8     RETURNS type
 9     [characteristic ...] routine_body
10 proc_parameter:
11     [ IN | OUT | INOUT ] param_name type
12 func_parameter:
13     param_name type
14 type:
15     Any valid MySQL data type
16 characteristic:
17     COMMENT 'string'
18   | LANGUAGE SQL
19   | [NOT] DETERMINISTIC
20   | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
21   | SQL SECURITY { DEFINER | INVOKER }
22 routine_body:
23     Valid SQL routine statement
View Code

其中有幾個注意點是:

1,DEFINER你能夠用這個選項指定能夠調用該PROCEDURE的用戶,好比說容許本地的用戶nero使用,那麼能夠指定爲:DEFINER='nero'@'localhost',若是這個事務就是建立給當前用戶使用的,那麼能夠指定爲:DEFINER=CURRENT_USER。

2,事務安全性:characteristic中若是使用了SQL SECURITY,那麼事務每次執行的時候,指定的安全上下文都會被執行,它們會檢查當前執行這個事務的人是否擁有執行權限。

好比說下面這個小例子:

delimiter //         --指定臨時分隔符
CREATE DEFINER = 'nero'@'localhost' PROCEDURE simpleTest(OUT outParam int, IN inParam int) SQL SECURITY INVOKE
BEGIN
    SELECT COUNT(*) INTO outParam FROM tbl WHERE col < inParam;
END;
delimter ;           

像上面這個例子,咱們在定義的時候啓用了「SQL SECURITY INVOKE」,只有是:a,對這個事務有調用權限;b,對這個表tbl有select權限的用戶才能成功執行該PROCEDURE

而在形參部分,則是經過OUTIN指明參數傳入仍是傳出,若是某個參數在傳入以後要做爲結果傳出,那麼不須要做特定指示,直接寫明參數名稱和參數類型便可。

調用這個事務則用CALL表達式便可:

SET @b=100;
CALL simpleTest(@a,@b);
SELECT @a;      --顯示結果

3、PROCEDURE小進階:

知道PROCEDURE的基本語法之後,學習一下編寫一個PROCEDURE常常須要用到的語句,分別有:DECLARE聲明語句,SET設值語句,DECLARE...HANDLER句柄聲明語句,DECLARE...CURSOR遊標聲明語句;條件判斷IFCASE;三種循環體:LOOP,REPEAT,WHILE

3.一、基本的DECLARE語句:

DECLARE基本語法:

DECLARE var_name [, var_name] ... type [DEFAULT value]

好比說在某個事務中聲明幾個臨時變量:

CREATE PROCEDURE test()
BEGIN
  DECLARE usrID INT ;
  DECLARE usrName VARCHAR(10) DEFAULT 'NERO';
  ..........               --一些事務操做
END;

3.二、聲明HANDLER句柄:

基本語法:

 1 DECLARE handler_type HANDLER
 2     FOR condition_value [, condition_value] ...
 3     statement
 4 handler_type:
 5     CONTINUE
 6   | EXIT
 7   | UNDO
 8 condition_value:
 9     SQLSTATE [VALUE] sqlstate_value
10   | condition_name
11   | SQLWARNING
12   | NOT FOUND
13   | SQLEXCEPTION
14   | mysql_error_code
View Code

句柄的做用,就是在condition_value中,若是指定的任意條件出現了,那麼statement這裏的指定語句就會被執行。conditions條件有幾種類型:

一、SQLSTATE指的是當前SQL返回的狀態,這個對應的狀態就比較多了,好比狀態Error: 1169 SQLSTATE: 23000,指的是」因特定限制而致使的沒法寫入的錯誤「;Error: 1162 SQLSTATE: 42000 ,指的是」結果字符串超過了最大限制「。相關的狀態代碼請自行查閱幫助文檔的」Server Error Codes and Messages「詞條。

二、SQLWARNING,但凡是SQL發出的警告信息。

三、NOT FOUND,通常來講出如今SELECT語句中,遊標觸底;

四、SQLEXCEPTION,SQL錯誤。

不一樣的結果分別對應:

一、CONTINUE,若是條件成立,那麼,在執行句柄的statement以後再繼續執行程序,好比說下面這個例子:

 1 CREATE TABLE tbl(col INT ,PRIMARY KEY(col));
 2 
 3 delimiter //
 4 
 5 CREATE PROCEDURE HANDLER_DEMO()
 6 BEGIN 
 7   DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
 8   SET @x = 1;
 9   INSERT INTO tbl VALUES(1);
10   SET @x = 2;
11   INSERT INTO tbl VALUES(1);  --觸發句柄的statement執行
12   SET @x = 3;
13 END;
14 //
15 
16 CALLL HANDLER_DEMO()//
17 
18 SELECT @x //
19 SELECT @x2 //
20 
21 delimiter ;

結果固然是@x爲3,@x2爲1了。在代碼11行,重複插入相同的值到主鍵上觸發了23000錯誤,於是執行statement:SET @x2 = 1,而後再繼續執行主程序的SET @x = 3.

二、EXIT,一旦條件被觸發,當前BEGIN...END閉合語句將會終止執行,好比說:

1 delimiter //
2 CREATE PROCEDURE EXIT_DEMO()
3 BEGIN 
4   BEGIN
5   DECLARE EXIT HANDLER FOR SQLSTATE '23000'
6   .......
7   END;
8 END;
9 delimiter ;

上述代碼中,一旦出現23000錯誤,代碼行4到7的BEGIN...END閉合語句馬上終止執行。

3.三、聲明CURSOR遊標 :

 聲明一個CURSOR遊標:

DECLARE cursor_name CURSOR FOR select_statement

好比說最基本的:

DECLARE cur1 CURSOR FOR SELECT id,data FROM tbl;

此時cur1表示的便是SELECT語句返回的首個結果,有點相似於指針。

下面不妨看一個比較完整的例子:

 1 delimiter //
 2 CREATE PROCEDURE CURSOR_DEMO()
 3 BEGIN
 4   DECLARE done INT DEFAULT 0;   --INT型值,默認爲0
 5   DECLARE a CHAR(5);
 6   DECLARE b,c INT;
 7   /*聲明兩個遊標*/
 8   DECLARE CUR1 CURSOR FOR SELECT ID,DATA FROM tbl1;
 9   DECLARE CUR2 CURSOR FOR SELECT I FROM tbl2;
10   /*聲明CONTINUE句柄,當遊標觸底時被觸發*/
11   DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
12   
13   /*打開遊標*/
14   OPEN CUR1;
15   OPEN CUR2;
16 
17   /*循環插入數據,使用REPEAT...UNTIL語句*/
18   REPEAT
19     FETCH CUR1 INTO a,b;       --讀取遊標中的數據,並移向下一行
20     FETCH CUR2 INTO c;
21     IF NOT done THEN       --當done爲0的時候條件成立
22       IF b < c THEN            --取b和c的較小者插入表3
23          INSERT INTO tbl3 VALUES(a,b);
24       ELSE
25          INSERT INTO tbl3 VALUES(a,c);
26       END IF;
27     END IF;  --當遊標觸底,句柄將被觸發,done值被設爲1,而後從這裏繼續執行主程序
28   UNTIL done  --句柄觸發後,done爲1,執行UNTIL
29   END REPEAT;
30   
31   /*使用完畢,關閉遊標*/
32   CLOSE CUR1;
33   CLOSE CUR2;
34 END//
35 
36 delimiter ;

其中,FETCH語句的基本語法以下:

FETCH cursor_name INTO var_name [, var_name] ...

該語句每次都會返回SELECT結果中的下一行(若是有的話)。

 3.四、循環語句:

循環涉及到的語句有:一、LOOP、ITERATE和LEAVE;二、REPEAT;三、WHILE

下面直接給出對應的循環例子:

一、LOOP、ITERATE和LEAVE:

/*LOOP,ITERATE,LEAVE*/
delimiter //

CREATE PROCEDURE LOOP_DEMO(param INT)
BEGIN 
  label1: LOOP
       SET param = param +1;
       IF param < 100 THEN
          ITERATE label1;   --回到標籤開始處
       END IF;
       LEAVE label1;          --離開標籤,退出流控制結構
  END LOOP label1;         --結束循環
END;

delimiter ;

二、REPEAT:

先給出REPEAT語法定義:

1 [begin_label:] REPEAT
2     statement_list
3 UNTIL search_condition
4 END REPEAT [end_label]

可見,一樣是能夠在代碼開始處插入label標籤,不過REPEAT循環是本身有控制條件的,最好能直接使用UNTIL來進行條件判斷。

好比下面這個例子:

 1 delimiter //
 2 CREATE PROCEDURE REPEAT_DEMO(param INT)
 3 BEGIN 
 4   SET @x = 0;
 5   REPEAT 
 6   SET @x = @x+1;
 7   UNTIL @x > param
 8   END REPEAT;
 9 END//
10 
11 delimiter ;

三、WHILE:

WHILE循環語法定義以下:

[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

好比下面這個小例子:

delimiter //

CREATE PROCEDURE WHILE_DEMO()
BEGIN 
  SET param INT DEFAULT 10;
  WHILE param < 1000
      ....              --循環內書寫具體須要處理的事務
      SET param = param + 100;
  END WHILE;
END;

delimiter ; 

4、順帶提一下觸發器TRIGGER:

觸發器都是和某個特定的表相關聯的,對該表設定觸發器之後,一旦對這個表進行了某個特定操做(諸如INSERT,UPDATE,DELETE),觸發器就會被觸發。

先給出CREATE TRIGGER語法定義:

CREATE
    [DEFINER = { user | CURRENT_USER }]
    TRIGGER trigger_name trigger_time trigger_event
    ON tbl_name FOR EACH ROW trigger_body

一樣的,能夠經過DEFINER自行指定觸發器的適用對象。

在trigger_time中能夠指定觸發時間(諸如:BEFORE,AFTER),trigger_event前面已經提到過了,另外,DROP TABLE或TRUNCATE TABLE這種操做是不會觸發TRIGGER的。

下面給出個小例子:

1 delimiter //
2 CREATE  DEFINER 'nero'@'localhost' TRIGGER trigger_demo
3 BEFORE INSERT ON tbl1 FOR EACH ROW
4 BEGIN
5   INSERT INTO tbl2 VALUES(...........);  --INSERT操做
6   DELETE FROM tbl3 WHERE ..........  ;  --刪除操做
7   UPDATE tbl4 SET col1 = ......          ;  --更新操做
8 END; //
9 delimiter ;

這樣,一旦本地用戶nero對錶tbl1進行INSERT操做的時候(以前,這裏設置的是BEFORE),BEGIN...END內的內容就會被執行。

相關文章
相關標籤/搜索