在本教學中,您將學習如何使用SIGNAL
和RESIGNAL
語句來引發存儲過程中的錯誤條件。
MySQL SIGNAL語句
使用SIGNAL
語句在存儲的程式(例如存儲過程,存儲函數,觸發器或事件)中向調用者返回錯誤或警告條件。 SIGNAL
語句提供了對返回值(如值和消息SQLSTATE
)的資訊的控制。
以下說明SIGNAL
語句的語法:
SIGNAL SQLSTATE | condition_name;
SET condition_information_item_name_1 = value_1,
condition_information_item_name_1 = value_2, etc;
SIGNAL
關鍵字是由DECLARE CONDITION
語句聲明的SQLSTATE
值或條件名稱。 請注意,SIGNAL
語句必須始終指定使用SQLSTATE
值定義的SQLSTATE
值或命名條件。
要向調用者提供資訊,請使用SET
子句。如果要使用值返回多個條件資訊項名稱,則需要用逗號分隔每個名稱/值對。
condition_information_item_name
可以是MESSAGE_TEXT
,MYSQL_ERRORNO
,CURSOR_NAME
等。
以下存儲過程將訂單行專案添加到現有銷售訂單中。 如果訂單號碼不存在,它會發出錯誤消息。
DELIMITER $$
CREATE PROCEDURE AddOrderItem(in orderNo int,
in productCode varchar(45),
in qty int,in price double, in lineNo int )
BEGIN
DECLARE C INT;
SELECT COUNT(orderNumber) INTO C
FROM orders
WHERE orderNumber = orderNo;
-- check if orderNumber exists
IF(C != 1) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Order No not found in orders table';
END IF;
-- more code below
-- ...
END $$
DELIMITER ;
首先,它使用傳遞給存儲過程的輸入訂單號對訂單進行計數。
第二步,如果訂單數不是1
,它會引發SQLSTATE 45000的錯誤以及orders
表中不存在訂單號的錯誤消息。
請注意,
45000
是一個通用SQLSTATE
值,用於說明未處理的用戶定義異常。
如果調用存儲過程AddOrderItem()
,但是傳遞不存在的訂單號,那麼將收到一條錯誤消息。
CALL AddOrderItem(10,'S10_1678',1,95.7,1);
執行上面代碼,得到以下結果 -
mysql> CALL AddOrderItem(10,'S10_1678',1,95.7,1);
1644 - Order No not found in orders table
mysql>
MySQL RESIGNAL語句
除了SIGNAL
語句,MySQL還提供了用於引發警告或錯誤條件的RESIGNAL
語句。
RESIGNAL
語句在功能和語法方面與SIGNAL
語句相似,只是:
- 必須在錯誤或警告處理程式中使用
RESIGNAL
語句,否則您將收到一條錯誤消息,指出“RESIGNAL when handler is not active
”。 請注意,您可以在存儲過程中的任何位置使用SIGNAL
語句。 - 可以省略
RESIGNAL
語句的所有屬性,甚至可以省略SQLSTATE
值。
如果單獨使用RESIGNAL
語句,則所有屬性與傳遞給條件處理程式的屬性相同。
以下存儲過程在將發送給調用者之前更改錯誤消息。
DELIMITER $$
CREATE PROCEDURE Divide(IN numerator INT, IN denominator INT, OUT result double)
BEGIN
DECLARE division_by_zero CONDITION FOR SQLSTATE '22012';
DECLARE CONTINUE HANDLER FOR division_by_zero
RESIGNAL SET MESSAGE_TEXT = 'Division by zero / Denominator cannot be zero';
--
IF denominator = 0 THEN
SIGNAL division_by_zero;
ELSE
SET result := numerator / denominator;
END IF;
END $$
DELIMITER ;
下麵我們來調用Divide()
存儲過程。
CALL Divide(10,0,@result);
執行上面語句,得到以下結果 -
mysql> CALL Divide(10,0,@result);
1644 - Division by zero / Denominator cannot be zero
在本教學中,我們向您展示了如何使用SIGNAL
和RESIGNAL
語句引發存儲程式中的錯誤條件。