一、概述
變量在存儲過程中會經常被使用,變量的使用方法是一個重要的知識點,特別是在定義條件這塊比較重要。
mysql版本:5.6
二、變量定義和賦值
#創建數據庫 DROP DATABASE IF EXISTS Dpro; CREATE DATABASE Dpro CHARACTER SET utf8 ; USE Dpro; #創建部門表 DROP TABLE IF EXISTS Employee; CREATE TABLE Employee (id INT NOT NULL PRIMARY KEY COMMENT '主鍵', name VARCHAR(20) NOT NULL COMMENT '人名', depid INT NOT NULL COMMENT '部門id' ); INSERT INTO Employee(id,name,depid) VALUES(1,'陳',100),(2,'王',101),(3,'張',101),(4,'李',102),(5,'郭',103);
declare定義變量
在存儲過程和函數中通過declare定義變量在BEGIN...END中,且在語句之前。並且可以通過重復定義多個變量
注意:declare定義的變量名不能帶‘@'符號,mysql在這點做的確實不夠直觀,往往變量名會被錯成參數或者字段名。
DECLARE var_name[,...] type [DEFAULT value]
例如:
DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陳'; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid; END$$ DELIMITER ;
SET變量賦值
SET除了可以給已經定義好的變量賦值外,還可以指定賦值並定義新變量,且SET定義的變量名可以帶‘@'符號,SET語句的位置也是在BEGIN ....END之間的語句之前。
1.變量賦值
SET var_name = expr [, var_name = expr] ... DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陳'; SET pname='王'; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount); SELECT @pcount;
2.通過賦值定義變量
DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陳'; SET pname='王'; SET @ID=1; SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname; SELECT @ID; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount);
SELECT ... INTO語句賦值
通過select into語句可以將值賦予變量,也可以之間將該值賦值存儲過程的out參數,上面的存儲過程select into就是之間將值賦予out參數。
DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN DECLARE pname VARCHAR(20) DEFAULT '陳'; DECLARE Pid INT; SELECT COUNT(id) INTO Pid FROM Employee WHERE depid=pdepid AND name=pname; SELECT Pid; END$$ DELIMITER ; CALL Pro_Employee(101,@pcount);
這個存儲過程就是select into將值賦予變量;
表中並沒有depid=101 and name='陳'的記錄。
三、條件
條件的作用一般用在對指定條件的處理,比如我們遇到主鍵重復報錯後該怎樣處理。
定義條件
定義條件就是事先定義某種錯誤狀態或者sql狀態的名稱,然後就可以引用該條件名稱開做條件處理,定義條件一般用的比較少,一般會直接放在條件處理裡面。
DECLARE condition_name CONDITION FOR condition_value condition_value: SQLSTATE [VALUE] sqlstate_value | mysql_error_code
1.沒有定義條件:
DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陳',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陳',100); SET @ID=3; END$$ DELIMITER ; #執行存儲過程 CALL Pro_Employee_insert(); #查詢變量值 SELECT @ID,@X;
報主鍵重復的錯誤,其中1062是主鍵重復的錯誤代碼,23000是sql錯誤狀態
2.定義處理條件
DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #定義條件名稱, DECLARE reprimary CONDITION FOR 1062; #引用前面定義的條件名稱並做賦值處理 DECLARE EXIT HANDLER FOR reprimary SET @x=1; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陳',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陳',100); SET @ID=3; END$$ DELIMITER ; CALL Pro_Employee_insert(); SELECT @ID,@X;
在執行存儲過程的步驟中並沒有報錯,但是由於我定義的是exit,所以在遇到報錯sql就終止往下執行了。
接下來看看continue的不同
DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #定義條件名稱, DECLARE reprimary CONDITION FOR SQLSTATE '23000'; #引用前面定義的條件名稱並做賦值處理 DECLARE CONTINUE HANDLER FOR reprimary SET @x=1; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(1,'陳',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陳',100); SET @ID=3; END$$ DELIMITER ; CALL Pro_Employee_insert(); SELECT @ID,@X;
其中紅色標示的是和上面不同的地方,這裡定義條件使用的是SQL狀態,也是主鍵重復的狀態;並且這裡使用的是CONTINUE就是遇到錯誤繼續往下執行。
條件處理
條件處理就是之間定義語句的錯誤的處理,省去了前面定義條件名稱的步驟。
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type: CONTINUE| EXIT| UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code
handler_type:遇到錯誤是繼續往下執行還是終止,目前UNDO還沒用到。
CONTINUE:繼續往下執行
EXIT:終止執行
condition_values:錯誤狀態
SQLSTATE [VALUE] sqlstate_value:就是前面講到的SQL錯誤狀態,例如主鍵重復狀態SQLSTATE '23000'
condition_name:上面講到的定義條件名稱;
SQLWARNING:是對所有以01開頭的SQLSTATE代碼的速記,例如:DECLARE CONTINUE HANDLER FOR SQLWARNING。
NOT FOUND:是對所有以02開頭的SQLSTATE代碼的速記。
SQLEXCEPTION:是對所有沒有被SQLWARNING或NOT FOUND捕獲的SQLSTATE代碼的速記。
mysql_error_code:是錯誤代碼,例如主鍵重復的錯誤代碼是1062,DECLARE CONTINUE HANDLER FOR 1062
語句:
DROP PROCEDURE IF EXISTS Pro_Employee_insert; DELIMITER $$ CREATE PROCEDURE Pro_Employee_insert() MODIFIES SQL DATA SQL SECURITY INVOKER BEGIN #引用前面定義的條件名稱並做賦值處理 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x=2; #開始事務必須在DECLARE之後 START TRANSACTION ; SET @ID=1; INSERT INTO Employee(id,name,depid) VALUES(7,'陳',100); SET @ID=2; INSERT INTO Employee(id,name,depid) VALUES(6,'陳',100); SET @ID=3; IF @x=2 THEN ROLLBACK; ELSE COMMIT; END IF; END$$ DELIMITER ; #執行存儲過程 CALL Pro_Employee_insert(); #查詢 SELECT @ID,@X;
通過SELECT @ID,@X可以知道存儲過程已經執行到了最後,但是因為存儲過程後面有做回滾操作整個語句進行了回滾,所以ID=7的符合條件的記錄也被回滾了。
總結
變量的使用不僅僅只有這些,在光標中條件也是一個很好的功能,剛才測試的是continue如果使用EXIT的話語句執行完“SET @ID=2;”就不往下執行了,後面的IF也不被執行整個語句不會被回滾,但是使用CONTINE當出現錯誤後還是會往下執行如果後面的語句還有很多的話整個回滾的過程將會很長,在這裡可以利用循環,當出現錯誤立刻退出循環執行後面的if回滾操作,在下一篇講循環語句會寫到,歡迎關注。