MySQL存儲過程中的遊標使用、循環簡單實例

 MySQL 5.0 版本開始支持存儲過程。

存儲過程(Stored Procedure)是一種在數據庫中存儲複雜程序,以便外部程序調用的一種數據庫對象。

存儲過程是爲了完成特定功能的SQL語句集,經編譯創建並保存在數據庫中,用戶可通過指定存儲過程的名字並給定參數(需要時)來調用執行。

存儲過程思想上很簡單,就是數據庫 SQL 語言層面的代碼封裝與重用。

 

優點

  • 存儲過程可封裝,並隱藏複雜的商業邏輯。
  • 存儲過程可以回傳值,並可以接受參數。
  • 存儲過程無法使用 SELECT 指令來運行,因爲它是子程序,與查看錶,數據表或用戶定義函數不同。
  • 存儲過程可以用在數據檢驗,強制實行商業邏輯等。

創建存儲過程

CREATE
    [DEFINER = { user | CURRENT_USER }]
 PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body
 
proc_parameter:
    [ IN | OUT | INOUT ] param_name type
 
characteristic:
    COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
 
routine_body:
  Valid SQL routine statement
 
[begin_label:] BEGIN
  [statement_list]
    ……
END [end_label]

 

MYSQL 存儲過程中的關鍵語法

-- 聲明語句結束符,可以自定義:
DELIMITER $$
或
DELIMITER //


-- 聲明存儲過程:
CREATE PROCEDURE demo_in_parameter(IN p_in int)

    
-- 存儲過程開始和結束符號:
BEGIN .... END


-- 變量賦值:
SET @p_in=1


-- 變量定義:
DECLARE l_int int unsigned default 4000000;


-- 創建mysql存儲過程、存儲函數:
create procedure 存儲過程名(參數)


-- 存儲過程體:
create function 存儲函數名(參數)

 

聲明異常處理的語法

-- 聲明異常處理的語法結構
DECLARE
{EXIT | CONTINUE}
HANDLER FOR
{error-number | SQLSTATE error-string | condition}
SQL statement


上述定義包括:
Handler Type (CONTINUE,EXIT)//處理類型 繼續或退出
Handler condition (SQLSTATE,MYSQL ERROR,CONDITION)//觸發條件
Handler actions(錯誤觸發的操作)


注意:
1、exit只退出當前的block。exit 意思是當動作成功提交後,退出所在的複合語句。即declare exit handler for... 所在的複合語句。
2、如果定義了handler action,會在continue或exit之前執行


發生錯誤的條件有:
1、MYSQL錯誤代碼
2、ANSI-standard SQLSTATE code
3、命名條件。可使用系統內置的SQLEXCEPTION,SQLWARNING和NOT FOUND


命名條件:
declare conditon_name condition for {SQLSTATE sqlstate_code | MYSQL_ERROR_CODE};

附常見錯誤號對照表

MySQL error code SQLSTATE code Error message

1011 HY000 Error on delete of '%s' (errno: %d)
1021 HY000 Disk full (%s); waiting for someone to free some space . . .
1022 23000 Can't write; duplicate key in table '%s'
1027 HY000 '%s' is locked against change
1036 HY000 Table '%s' is read only
1048 23000 Column '%s' cannot be null
1062 23000 Duplicate entry '%s' for key %d
1099 HY000 Table '%s' was locked with a READ lock and can't be updated
1100 HY000 Table '%s' was not locked with LOCK TABLES
1104 42000 The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
1106 42000 Incorrect parameters to procedure '%s'
1114 HY000 The table '%s' is full
1150 HY000 Delayed insert thread couldn't get requested lock for table %s
1165 HY000 INSERT DELAYED can't be used with table '%s' because it is locked with LOCK TABLES
1242 21000 Subquery returns more than 1 row
1263 22004 Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld
1264 22003 Out of range value adjusted for column '%s' at row %ld
1265 1000 Data truncated for column '%s' at row %ld
1312 0A000 SELECT in a stored program must have INTO
1317 70100 Query execution was interrupted
1319 42000 Undefined CONDITION: %s
1325 24000 Cursor is already open
1326 24000 Cursor is not open
1328 HY000 Incorrect number of FETCH variables
1329 2000 No data to FETCH
1336 42000 USE is not allowed in a stored program
1337 42000 Variable or condition declaration after cursor or handler declaration
1338 42000 Cursor declaration after handler declaration
1339 20000 Case not found for CASE statement
1348 HY000 Column '%s' is not updatable
1357 HY000 Can't drop a %s from within another stored routine
1358 HY000 GOTO is not allowed in a stored program handler
1362 HY000 Updating of %s row is not allowed in %s trigger
1363 HY000 There is no %s row in %s trigger

-- 錯誤異常處理片段
-- 遊標循環變量,遍歷數據結束標誌,默認false
DECLARE done INT DEFAULT FALSE;
DECLARE cur_account CURSOR FOR SELECT id,`status` FROM adm_users;


-- 當錯誤代碼爲1329時將 done 的值設爲TRUE,並繼續執行當前任務
DECLARE CONTINUE HANDLER FOR 1329 SET done = TRUE;

-- 也可以這麼寫:使用的條件爲ANSI標準錯誤代碼
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;

-- 也可以這麼寫
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

 

實例 

DELIMITER $$
CREATE PROCEDURE cs() -- 創建存儲過程
	BEGIN -- 開始存儲過程
	
	DECLARE vid INT(10) UNSIGNED DEFAULT 0;   -- 自定義變量id
	DECLARE vstu TINYINT(1) UNSIGNED DEFAULT 0;   -- 自定義變量id
	
	-- 遊標循環變量,遍歷數據結束標誌,默認false
	DECLARE done INT DEFAULT FALSE;
	
	-- 定義遊標並輸入結果集
	DECLARE cur_account CURSOR FOR SELECT id,`status` FROM adm_users;
	
	-- 將結束標誌綁定到遊標,遊標循環結束自動轉true
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
	
	-- 打開遊標
	OPEN  cur_account;
	
	-- 開始循環,read_loop爲自定義循環名,結束循環時用到
	read_loop: LOOP
	
		-- 取值 將遊標當前讀取行的數據順序賦予自定義變量
		FETCH cur_account INTO vid,vstu;
		
		-- 判斷是否繼續循環
		IF done THEN
			LEAVE read_loop; -- 結束循環
		END IF;
		
		-- 你自己想做的操作
		-- SELECT vid,vstu;
		
		-- 重新插入一條語句
		INSERT INTO `adm_users`(`username`, `password`, `verify_pwd`, `name`, `type`, `gid`, `status`, `add_time`) 
SELECT `username`, `password`, `verify_pwd`, `name`, `type`, `gid`, `status`, UNIX_TIMESTAMP() AS `add_time` FROM `adm_users` WHERE id = vid;
		SELECT vid,vstu,LAST_INSERT_ID() AS fristin;
        
	-- 結束自定義循環體
	END LOOP read_loop;
	
	CLOSE cur_account; -- 關閉遊標
	
	END $$ -- 結束存儲過程
DELIMITER ;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章