MySQL定義條件和處理程式

2020-07-16 10:05:25
在程式的執行過程中可能會遇到問題,此時我們可以通過定義條件和處理程式來事先定義這些問題。

定義條件是指事先定義程式執行過程中遇到的問題,處理程式定義了在遇到這些問題時應當採取的處理方式和解決辦法,保證儲存過程和函數在遇到警告或錯誤時能繼續執行,從而增強程式處理問題的能力,避免程式出現異常被停止執行。

下面將詳細講解如何定義條件和處理程式。

1. 定義條件

MySQL 中可以使用 DECLARE 關鍵字來定義條件。其基本語法如下:
DECLARE condition_name CONDITION FOR condition_value
condition value:
SQLSTATE [VALUE] sqlstate_value | mysql_error_code
其中:
  • condition_name 參數列示條件的名稱;
  • condition_value 參數列示條件的型別;
  • sqlstate_value 引數和 mysql_error_code 引數都可以表示 MySQL 的錯誤。sqlstate_value 表示長度為 5 的字串型別錯誤程式碼,mysql_error_code 表示數值型別錯誤程式碼。例如 ERROR 1146(42S02) 中,sqlstate_value 值是 42S02,mysql_error_code 值是 1146。

例 1

下面定義“ERROR 1146 (42S02)”這個錯誤,名稱為 can_not_find。 可以用兩種不同的方法來定義,程式碼如下:
//方法一:使用sqlstate_value
DECLARE can_not_find CONDITION FOR SQLSTATE '42S02';

//方法二:使用 mysql_error_code
DECLARE can_not_find CONDITION FOR 1146;

2. 定義處理程式

MySQL 中可以使用 DECLARE 關鍵字來定義處理程式。其基本語法如下:
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 引數指明錯誤的處理方式,該引數有 3 個取值。這 3 個取值分別是 CONTINUE、EXIT 和 UNDO。
  • CONTINUE 表示遇到錯誤不進行處理,繼續向下執行;
  • EXIT 表示遇到錯誤後馬上退出;
  • UNDO 表示遇到錯誤後撤回之前的操作,MySQL 中暫時還不支援這種處理方式。

注意:通常情況下,執行過程中遇到錯誤應該立刻停止執行下面的語句,並且撤回前面的操作。但是,MySQL 中現在還不能支援 UNDO 操作。因此,遇到錯誤時最好執行 EXIT 操作。如果事先能夠預測錯誤型別,並且進行相應的處理,那麼可以執行 CONTINUE 操作。

引數指明錯誤型別,該引數有 6 個取值:
  • sqlstate_value:包含 5 個字元的字串錯誤值;
  • condition_name:表示 DECLARE 定義的錯誤條件名稱;
  • SQLWARNING:匹配所有以 01 開頭的 sqlstate_value 值;
  • NOT FOUND:匹配所有以 02 開頭的 sqlstate_value 值;
  • SQLEXCEPTION:匹配所有沒有被 SQLWARNING 或 NOT FOUND 捕獲的 sqlstate_value 值;
  • mysql_error_code:匹配數值型別錯誤程式碼。

sp_statement 引數為程式語句段,表示在遇到定義的錯誤時,需要執行的一些儲存過程或函數。

例 2

下面是定義處理程式的幾種方式,程式碼如下:
//方法一:捕獲 sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='CAN NOT FIND';

//方法二:捕獲 mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info='CAN NOT FIND';

//方法三:先定義條件,然後呼叫
DECLARE can_not_find CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR can_not_find SET @info='CAN NOT FIND';

//方法四:使用 SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';

//方法五:使用 NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND';

//方法六:使用 SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';
上述程式碼是 6 種定義處理程式的方法。
  1. 捕獲 sqlstate_value 值。如果遇到 sqlstate_value 值為 42S02,執行 CONTINUE 操作,並且輸出“CAN NOT FIND”資訊。
  2. 捕獲 mysql_error_code 值。如果遇到 mysql_error_code 值為 1146, 執行 CONTINUE 操作,並且輸出“CAN NOT FIND”資訊。
  3. 先定義條件,然後再呼叫條件。這裡先定義 can_not_find 條件,遇到 1146 錯誤就執行 CONTINUE 操作。
  4. 使用 SQLWARNING。SQLWARNING 捕獲所有以 01 開頭的 sqlstate_value 值,然後執行 EXIT 操作,並且輸出“ERROR"資訊。
  5. 使用 NOT FOUND。NOT FOUND 捕獲所有以 02 開頭的 sqlstate_value 值,然後執行 EXIT 操作,並且輸出“CAN NOT FIND”資訊。
  6. 使用 SQLEXCEPTION。 SQLEXCEPTION 捕獲所有沒有被 SQLWARNING 或 NOT FOUND 捕獲的 sqlstate_value 值,然後執行 EXIT 操作,並且輸出“ERROR”資訊。

例 3

定義條件和處理順序,具體的執行過程如下:
mysql> CREATE TABLE t8(s1 INT,PRIMARY KEY(s1));
Query OK, 0 rows affected (0.07 sec)

mysql> DELIMITER //
mysql> CREATE PROCEDURE handlerdemo()
    -> BEGIN
    -> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @X2=1;
    -> SET @X=1;
    -> INSERT INTO t8 VALUES(1);
    -> SET @X=2;
    -> INSERT INTO t8 VALUES(1);
    -> SET @X=3;
    -> END //
Query OK, 0 rows affected (0.02 sec)

mysql> DELIMITER ;
mysql> CALL handlerdemo();
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT @X;
+------+
| @X   |
+------+
|    3 |
+------+
1 row in set (0.00 sec)
上述程式碼中,@X 是一個使用者變數,執行結果 @X 等於 3,這表明 MySQL 執行到程式的末尾。

如果DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @X2=1;這一行不存在,第二個 INSERT 因 PRIMARY KEY 約束而失敗之後,MySQL 可能已經採取 EXIT 策略,且 SELECT @X 可能已經返回 2。

注意:@X 表示使用者變數,使用 SET 語句為其賦值,使用者變數與連線有關,一個用戶端定義的變數不能被其他用戶端所使用,當用戶端退出時,該用戶端連線的所有變數將自動釋放。