MYSQL的儲存過程的學習

MYSQL的儲存過程

儲存過程的創建、修改、刪除、調用

創建儲存過程

語法:
    CREATE PROCEDURE proc_name ([proc_parameter]) [characteristics...] body
講解:
    CREATE PROCEDURE:創建存儲過程關鍵字
    proc_name:存儲過程名稱
    proc_parameter:參數列表,可選,格式:[IN | OUT | INOUT] param_name type
        IN:輸入參數
        OUT:輸出參數
        INOUT:既可以輸入也可以輸出
        param_name:參數名稱
        type:參數類型,MySQL中的任意類型,如varchar等
    characteristics:指定存儲過程特性,取值如下:
        LANGUAGE SQL:說明body部分由SQL語句組成,LANGUAGE可選值只有SQL
        [NOT] DETERMINISTIC:指明存儲過程執行結果是否確定。默認值:NOT DETERMINISTIC
            DETERMINISTIC:結果確定,每次執行存儲過程時,相同的輸入會得到相同的輸出
            NOT DETERMINISTIC:結果不確定,相同輸入可能得到不同輸出。
        {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}:指定子程序使用存儲過程的限制。默認值:CONTAINS SQL
            CONTAINS SQL:說明子程序包含SQL語句,但是不包含寫數據語句
            NO SQL:說明子程序不包含SQL語句
            READS SQL DATA:說明子程序包含讀數據讀數據語句
            MODIFIES SQL DATA:說明子程序包含寫數據語句
        SQL SECURITY {DEFINER | INVOKER}:指明誰有權限執行,默認值:DEFINER
            DEFINER:只有定義者才能執行
            INVOKER:擁有權限的調用者纔可以執行
        COMMNET:註釋信息

創建調用

語法:
    CALL proc_name ([parameter[,...]])
案例:
    DELIMITER $$
    CREATE PROCEDURE proc_countByName(IN uname VARCHAR(100), OUT total INT)
    BEGIN
        SELECT COUNT(*) INTO total FROM njit_user WHERE NAME LIKE CONCAT('%', uname, '%');
    END $$

刪除存儲過程

語法:
    DROP {PROCEDURE | FUNCTION} [IF EXISTS] proc_name
刪除:
    DROP PROCEDURE  proc_countByName;
    DROP PROCEDURE IF EXISTS proc_countByName;

修改

語法:
    ALTER {PROCEDURE | FUNCTION} proc_or_func [characterustic...]
說明:
    {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}:指定子程序使用存儲過程的限制。
        CONTAINS SQL:說明子程序包含SQL語句,但是不包含寫數據語句
        NO SQL:說明子程序不包含SQL語句
        READS SQL DATA:說明子程序包含讀數據讀數據語句
        MODIFIES SQL DATA:說明子程序包含寫數據語句
    SQL SECURITY {DEFINER | INVOKER}:指明誰有權限執行,默認值:DEFINER
        DEFINER:只有定義者才能執行
        INVOKER:擁有權限的調用者纔可以執行
    COMMNET:註釋信息

查看狀態

語法:
    SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'parttern']
說明:
    這個語句是MySQL的擴展,它返回子程序的特徵,如數據庫、名字、類型、創建者及創建和修改日期。如果沒有指定樣式,根據使用的語句,所有存儲程序或存儲函數的信息都被列出。PROCEDURE和FUNCTION分別表示查看存儲過程和函數;LIKE語句表示匹配存儲過程或函數名稱。
案例:
    SHOW PROCEDURE STATUS LIKE 'proc_%';

儲存過程的基礎命令

### 創建存儲過程
-- 定義結束符[爲了PROCEDURE的結束符與mysql的普通語句不同]
delimiter //
-- 如果該儲存過程存在就刪除
DROP PROCEDURE IF EXISTS in_param;
-- 創建一個儲存過程[in_param],需要傳入參數inParam
CREATE PROCEDURE in_param(INOUT inParam VARCHAR(50))
-- 開始標識符
BEGIN
-- 定義變量
DECLARE var_param1 VARCHAR(50) DEFAULT "自定義變量默認值var_param1";
     -- 獲取數據值
     SELECT var_param1;
     -- 重新改變數據值
     SET var_param1='改變自定義的屬性值';
     -- 獲取數據值
     SELECT var_param1;
     -- 重新賦值
     select "運行into儲存值" into intoParam;
     select intoParam;
     -- 語句執行結束符
END //
-- 重新改變數據的結束的標識符
delimiter ;



### 調用存儲過程
語法:call sp_name()
注意:存儲過程名稱後面必須加括號,哪怕該存儲過程沒有參數傳遞



### 刪除存儲過程
語法:drop procedure sp_name
注意:不能在一個存儲過程中刪除另一個存儲過程,只能調用另一個存儲過程

儲存過程的簡單使用案例

-- 定義結束符[爲了PROCEDURE的結束符與mysql的普通語句不同]
delimiter //
-- 如果該儲存過程存在就刪除
DROP PROCEDURE IF EXISTS in_param;
-- 創建一個儲存過程[in_param],需要傳入參數inParam
CREATE PROCEDURE in_param(INOUT inParam VARCHAR(50))
-- 開始標識符
BEGIN
-- 定義變量
DECLARE var_param1 VARCHAR(50) DEFAULT "自定義變量默認值var_param1";
DECLARE intoParam VARCHAR(50) DEFAULT "自定義變量默認值intoParam";
     -- 獲取數據值
     SELECT var_param1;
     SELECT inParam;
     -- 重新改變數據值
     SET var_param1='改變自定義的屬性值';
     SET inParam='傳入值的修改';
     -- 獲取數據值
     SELECT var_param1;
     SELECT inParam;
     -- 重新賦值
     select "運行into儲存值" into intoParam;
     select intoParam;
     -- 語句執行結束符
END //
-- 重新改變數據的結束的標識符
delimiter ;
 
 
 
-- 調用儲存過程[儲存過程是傳入的參數當我們select @inParamStr輸出的是原始值,而不是過程內部修改之後的值,如果我們更改參數類型爲inout,則會輸出]
set @inParamStr="傳入參數";
CALL in_param(@inParamStr);
select @inParamStr;

儲存過程的變量的定義

變量的定義
   DECLARE [相同屬性的變量x ......] VARCHAR(50) DEFAULT "默認的初始化值";
改變變量值
   SET x= "修改之後的值";
改變變量值
   select "查詢改變之後的值" into x;

變量範圍(作用域)

一個變量有自己的範圍(作用域),它用來定義它的生命週期。 如果在存儲過程中聲明一個變量,那麼當達到存儲過程的END語句時,它將超出範圍,因此在其它代碼塊中無法訪問。
如果您在BEGIN END塊內聲明一個變量,那麼如果達到END,它將超出範圍。 可以在不同的作用域中聲明具有相同名稱的兩個或多個變量,因爲變量僅在自己的作用域中有效。 但是,在不同範圍內聲明具有相同名稱的變量不是很好的編程習慣。
以@符號開頭的變量是會話變量。直到會話結束前它可用和可訪問。

定義條件和處理程序

#定義條件
    語法:DECLARE cond_name CONDITION FOR [cond_type]
    解析:[cond_type]:SQLSTATE [VALUE] sqlstate_value(可選項) | mysql_erroe_code(可選項)
         cond_name:條件名稱
         cond_type:條件類型,用於定義MySQL的錯誤,SQLSTATE是長度爲5的字符串類型的錯誤代碼;mysql_error_code是數值類型的錯誤代碼。例如ERROR 1142(42000),sql_state_value的值是'42000',mysql_error_code的值是1142。
         
    示例:
        -- 使用SQLSTATE
        DECLARE cond_error CONDITION FOR SQLSTATE '42000';
        -- 使用mysql_error_code
        DECLARE cond_error CONDITION FOR 1148;

#定義處理程序
    語法:DECLARE handler_type HANDLER FOR  condition_value[,...] sp_statement
    解析:handler_type:指定錯誤處理方式
            CONTINUE:遇到錯誤不處理,繼續執行
            EXIT:遇到錯誤立即退出
            UNDO:遇到錯誤撤回之前的操作
         condition_value:表示錯誤類型
            SQLSTATE [VALUE] sqlstate_value:包含5個字符的字符串錯誤值
            mysql_error_code:數值類型的錯誤代碼
            cond_name:定義條件的名稱,見第一節
            SQLWARNING:匹配所有以01開頭的SQLSTATE錯誤代碼
            NOT FOUND:匹配所有以02開頭的SQLSTATE錯誤代碼
            SQL EXCEPTION:匹配所有沒有被SQLWARNING或NOT FOUND捕獲的SQLSTATE錯誤代碼
         sp_statement: 程序語句段
            程序語句段,表示在遇到定義的錯誤時執行的存儲過程或函數。
    
    示例:
        -- 捕獲SQLSTATE
        DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='NO_SUCH_TABLE';
        -- 捕獲mysql_error_code
        DECLARE CONTINUE HANDLER FOR SQLSTATE '1146' SET @info='NO_SUCH_TABLE' ;
        -- 捕獲定義條件
        DECLARE no_such_table CONDITION FOR 1146;
        DECLARE CONTINUE HANDLER FOR no_such_table SET @info='NO_SUCH_TABLE';
        -- 捕獲SQLWARNING
        DECLARE EXIT HANDLER FOR SQLWARNING set @info='ERROR';
        -- 捕獲NOT FOUND
        DECLARE EXIT HANDLER FOR NOT FOUND set @info='NO_SUCH_TABLE';
        -- 捕獲SQLEXCEPTION
        DECLARE EXIT HANDLER FOR SQLEXCEPTION set @info='ERROR';
        -- 捕獲所有異常
        DECLARE EXIT HANDLER FOR SQLWARNING, NOT FOUND,SQLEXCEPTION BEGIN ... END;



#存儲過程示例
DELIMITER $$
CREATE PROCEDURE proc_del_user(IN uid INT, OUT rowCount INT, OUT msg VARCHAR(200))
BEGIN
	-- 出錯標記
	DECLARE t_error INT DEFAULT 0;
	-- 定義出錯處理程序
	DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error = 1;
	
	-- 刪除用戶
	DELETE FROM t_user WHERE id = uid;
	
	-- 異常處理
	IF t_error = 0 THEN
		SET msg = 'success';
	ELSE
		SET msg = 'error';
	END IF;
	
	-- 設置真正影響行數的行數,修改了但是沒有修改值都不計入
	SET rowCount = ROW_COUNT();
	SELECT rowCount, msg;
END $$

-- 調用儲存過程
CALL proc_del_user(1, @rowCount, @msg);
SELECT @rowCount, @msg;

光標的使用

光標:查詢語句可能查詢出多條記錄,在存儲過程和函數中使用光標來逐條讀取查詢結果集中的記錄
步驟:聲明光標->打開光標->使用光標->關閉光標;
     光標必須聲明在處理程序之前,並且聲明在變量和條件之後。
     
語法:
    聲明光標:DECLARE cursor_name CURSOR FOR select_statement(sql命令); 
            cursor_name參數表示光標的名稱;select_statement參數表示SELECT語句的內容,返回一個用於創建光標的結果集
    打開光標:OPEN  cursor_name;
            cursor_name參數表示光標的名稱。
    使用光標:FETCH cur_employee INTO var_name[,var_name…] ; 
            cursor_name參數表示光標的名稱;var_name參數表示將光標中的SELECT語句查詢出來的信息存入該參數中。var_name必須在聲明光標之前就定義好
    關閉光標:CLOSE  cursor_name ; 
            cursor_name參數表示光標的名稱。關閉之後就不能使用FETCH來使用光標了
            
            
例子:
   begin 
    ##定義變量
    declare my_id varchar(32); 
    declare my_name varchar(50); 
    DECLARE done INT DEFAULT FALSE; 
    #創建遊標並存儲數據,
    DECLARE My_Cursor CURSOR FOR ( SELECT tid,tname FROM `teacher` ); 
    #遊標中內容執行完設置done爲1
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    #設置手動提交
    set autocommit=0;
    #打開遊標
    OPEN My_Cursor; 
    #執行循環
      myLoop: LOOP 
    #判斷是否結束循環
        IF done THEN 
          LEAVE myLoop; 
        END IF;
    #取出遊標中的值
        FETCH My_Cursor into my_id,my_name; 
    #更新數據
        UPDATE course SET cname = my_name WHERE teacher_id = my_id ; 
    
    
      END LOOP myLoop; 
    #釋放遊標
      CLOSE My_Cursor; 
     #提交
        COMMIT; 
    END

流程控制

流程控制:[IF語句、CASE語句、LOOP語句、LEAVE語句、ITERATE語句、REPEAT語句、WHILE]
語法:
    IF語句:[類似於java的if-else if-else]search_condition參數表示條件判斷語句;statement_list參數表示不同條件的執行語句[MYSQL還有一個IF()函數,他不同於這裏描述的IF語句]
        語法:
            IF search_condition THEN statement_list 
            [ELSEIF search_condition THEN statement_list] ... 
            [ELSE statement_list] 
            END IF
        案例:
            IF age>20 THEN SET @count1=@count1+1;  
            ELSEIF age=20 THEN SET @count2=@count2+1;  
            ELSE SET @count3=@count3+1;  
            END IF; 
    CASE語句:[類似於java的switch]case_value參數表示條件判斷的變量;when_value參數表示變量的取值;statement_list參數表示不同when_value值的執行語句
        語法:
            CASE case_value 
            WHEN when_value THEN statement_list 
            [WHEN when_value THEN statement_list] ... 
            [ELSE statement_list] 
            END CASE 
        案例:
            CASE age 
            WHEN 20 THEN SET @count1=@count1+1; 
            ELSE SET @count2=@count2+1; 
            END CASE ; 
    CASE另一種寫法:[類似於java的switch]CASE search_condition參數表示條件判斷語句;statement_list參數表示不同條件的執行語句;
        語法:
            WHEN search_condition THEN statement_list 
            [WHEN search_condition THEN statement_list] ... 
            [ELSE statement_list] 
            END CASE 
        案例:
            CASE 
            WHEN age=20 THEN SET @count1=@count1+1; 
            ELSE SET @count2=@count2+1; 
            END CASE;
        注意:注意:這裏的CASE語句和“控制流程函數”裏描述的SQL CASE表達式的CASE語句有輕微不同。這裏的CASE語句不能有ELSE NULL子句並且用END CASE替代END來終止!!
    LOOP語句:[類似於java的for]LOOP語句可以使某些特定的語句重複執行,實現一個簡單的循環,但是LOOP語句本身沒有停止循環的語句,必須是遇到LEAVE語句等才能停止循環
        語法:begin_label參數和end_label參數分別表示循環開始和結束的標誌,這兩個標誌必須相同,而且都可以省略;statement_list參數表示需要循環執行的語句
            [begin_label:] LOOP 
            statement_list 
            END LOOP [end_label] 
        案例:因爲沒有跳出循環的語句,這個循環成了一個死循環
            add_num: LOOP  
            SET @count=@count+1;  
            END LOOP add_num ; 
    LEAVE語句:[類似於java的return]LEAVE語句主要用於跳出循環控制
        語法:label參數表示循環的標誌
            LEAVE label
        案例:
            add_num: LOOP 
            SET @count=@count+1; 
            IF @count=100 THEN 
            LEAVE add_num ; 
            END LOOP add_num ;
    ITERATE語句:[類似於java的continue]ITERATE語句也是用來跳出循環的語句。但是,ITERATE語句是跳出本次循環,然後直接進入下一次循環;ITERATE語句只可以出現在LOOP、REPEAT、WHILE語句內
        語法:label參數表示循環的標誌
            ITERATE label
        案例:
            add_num: LOOP 
            SET @count=@count+1; 
            IF @count=100 THEN 
            LEAVE add_num ; 
            ELSE IF MOD(@count,3)=0 THEN 
            ITERATE add_num; 
            SELECT * FROM employee ; 
            END LOOP add_num ; 
    REPEAT語句:[類似於Java的do-while]REPEAT語句是有條件控制的循環語句。當滿足特定條件時,就會跳出循環語句
        語法:statement_list參數表示循環的執行語句;search_condition參數表示結束循環的條件,滿足該條件時循環結束
            [begin_label:] REPEAT 
            statement_list 
            UNTIL search_condition 
            END REPEAT [end_label] 
        案例:
            REPEAT 
            SET @count=@count+1; 
            UNTIL @count=100 
            END REPEAT ; 
    WHILE語句:[類似於Java的while]WHILE語句也是有條件控制的循環語句。但WHILE語句和REPEAT語句是不一樣的。WHILE語句是當滿足條件時,執行循環內的語句
        語法:search_condition參數表示循環執行的條件,滿足該條件時循環執行,statement_list參數表示循環的執行語句
            [begin_label:] WHILE search_condition DO 
            statement_list 
            END WHILE [end_label]
        案例:
            WHILE @count<100 DO 
            SET @count=@count+1; 
            END WHILE ; 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章