无法处理 MYSQL 函数中的异常
Unable to handle exception in MYSQL Function
我对MYSQL函数和异常处理不是很熟悉。经过所有的研究,我可以得出以下结论,但没有任何收获。
我正在尝试 return 如果插入语句执行失败则为 0,否则为 1。异常被引发而不是被处理。我哪里错了?
CREATE DEFINER=`myusr`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(6)) RETURNS int(1)
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
RETURN 0;
END;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`my_tbl`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END
TABLE - my_tbl
成功案例 - func1('ABC','123456')
异常情况 - func1('ABC','123456789')
编辑 - 添加了屏幕截图
似乎mysql 8.0.19 不能捕获所有错误并正确处理它们。
Error Code: 1406. Data too long for column 'p2' at row 1
Error Code: 1049. Unknown database 'mydb'
有两个例子我测试过但没有用,其他人这样做我认为这更适用于 mysql 论坛。
DELIMITER $$
CREATE DEFINER=`mydb`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(6)) RETURNS int
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIn
RETURN 0;
END;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`func1`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END;
DE§LIMITER ;
这个场景有效。我增加了引用变量 p2 的大小以适合输入的数据,并且我为错误 1265 添加了一个退出处理程序,这是您在尝试插入长文本时遇到的错误。
Error Code: 1265. Data truncated for column 'c2' at row 1
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(20)) RETURNS int
MODIFIES SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
BEGIN
DECLARE EXIT HANDLER FOR 1265 RETURN 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN 0;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`my_tbl`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END;
END$$
DELIMITER ;
你得到的错误,甚至在添加 HANDLER 之前就传递了错误消息
TRY语句的作用是捕获异常。 (因为这个过程通常包含几个语句,所以通常使用术语“TRY 块”而不是“TRY 语句”。)如果在 TRY 块内发生异常,系统中称为异常处理程序的部分将异常传递给其他部分程序的一部分,它将处理异常。此程序部分由关键字 CATCH 表示,因此称为 CATCH 块。
注意
使用 TRY 和 CATCH 语句进行异常处理是 C# 和 Java 等现代编程语言处理错误的常用方法。
用 TRY 和 CATCH 块处理异常给程序员带来很多好处,例如:
Exceptions provide a clean way to check for errors without cluttering code
Exceptions provide a mechanism to signal errors directly rather than using some side effects
Exceptions can be seen by the programmer and checked during the compilation process
SQL Server 2012 引入了与处理错误相关的第三个语句:THROW。此语句允许您抛出在异常处理块中捕获的异常。简单地说,THROW 语句是另一种 return 机制,其行为类似于已经描述的 RAISEERROR 语句。
示例 1 显示了 TRY/CATCH/THROW 异常处理的工作原理。它显示了如何使用异常处理批量插入所有语句或在发生错误时回滚整个语句组。该示例基于部门和员工 table 之间的引用完整性。因此,您必须使用 PRIMARY KEY 和 FOREIGN KEY 约束创建两个 table。
示例 1
0270_001
示例1中的batch执行后,batch中的3条语句都不会执行,本例输出为:
0271_001
示例 1 的执行过程如下。第一个 INSERT 语句执行成功。然后,第二个语句导致引用完整性错误。因为这三个语句都写在 TRY 块中,异常被“抛出”并且异常处理程序启动 CATCH 块。 CATCH 回滚所有语句并打印相应的消息。之后,THROW 语句 returns 向调用者执行批处理。因此,员工 table 的内容不会更改。
注意
语句 BEGIN TRANSACTION、COMMIT TRANSACTION 和 ROLLBACK 是关于事务的 Transact-SQL 语句。这些语句分别启动、提交和回滚事务。有关这些报表和交易的一般讨论,请参见第 13 章。
这里的问题是异常是在异常处理程序之外产生的。
在定义异常处理程序之前验证发送到函数的参数。要捕获该异常,您需要围绕函数调用的异常处理程序。
如果您声明 p2 varchar(20),并保留列定义 varchar(6),您可能会得到您想要的行为,因为这样异常将在异常处理程序所涵盖的代码内部触发。
我对MYSQL函数和异常处理不是很熟悉。经过所有的研究,我可以得出以下结论,但没有任何收获。
我正在尝试 return 如果插入语句执行失败则为 0,否则为 1。异常被引发而不是被处理。我哪里错了?
CREATE DEFINER=`myusr`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(6)) RETURNS int(1)
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
RETURN 0;
END;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`my_tbl`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END
TABLE - my_tbl
成功案例 - func1('ABC','123456')
异常情况 - func1('ABC','123456789')
编辑 - 添加了屏幕截图
似乎mysql 8.0.19 不能捕获所有错误并正确处理它们。
Error Code: 1406. Data too long for column 'p2' at row 1
Error Code: 1049. Unknown database 'mydb'
有两个例子我测试过但没有用,其他人这样做我认为这更适用于 mysql 论坛。
DELIMITER $$
CREATE DEFINER=`mydb`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(6)) RETURNS int
READS SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIn
RETURN 0;
END;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`func1`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END;
DE§LIMITER ;
这个场景有效。我增加了引用变量 p2 的大小以适合输入的数据,并且我为错误 1265 添加了一个退出处理程序,这是您在尝试插入长文本时遇到的错误。
Error Code: 1265. Data truncated for column 'c2' at row 1
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `func1`(p1 varchar(50), p2 varchar(20)) RETURNS int
MODIFIES SQL DATA
DETERMINISTIC
BEGIN
DECLARE EXP DATETIME;
DECLARE RINT INT(1);
BEGIN
DECLARE EXIT HANDLER FOR 1265 RETURN 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN 0;
SET exp = DATE_ADD(NOW(), INTERVAL 15 MINUTE);
INSERT INTO `mydb`.`my_tbl`
(`C1`,
`C2`,
`C3`)
VALUES
(p1, p2, exp);
SET RINT = 1;
RETURN RINT;
END;
END$$
DELIMITER ;
你得到的错误,甚至在添加 HANDLER 之前就传递了错误消息
TRY语句的作用是捕获异常。 (因为这个过程通常包含几个语句,所以通常使用术语“TRY 块”而不是“TRY 语句”。)如果在 TRY 块内发生异常,系统中称为异常处理程序的部分将异常传递给其他部分程序的一部分,它将处理异常。此程序部分由关键字 CATCH 表示,因此称为 CATCH 块。
注意
使用 TRY 和 CATCH 语句进行异常处理是 C# 和 Java 等现代编程语言处理错误的常用方法。
用 TRY 和 CATCH 块处理异常给程序员带来很多好处,例如:
Exceptions provide a clean way to check for errors without cluttering code
Exceptions provide a mechanism to signal errors directly rather than using some side effects
Exceptions can be seen by the programmer and checked during the compilation process
SQL Server 2012 引入了与处理错误相关的第三个语句:THROW。此语句允许您抛出在异常处理块中捕获的异常。简单地说,THROW 语句是另一种 return 机制,其行为类似于已经描述的 RAISEERROR 语句。
示例 1 显示了 TRY/CATCH/THROW 异常处理的工作原理。它显示了如何使用异常处理批量插入所有语句或在发生错误时回滚整个语句组。该示例基于部门和员工 table 之间的引用完整性。因此,您必须使用 PRIMARY KEY 和 FOREIGN KEY 约束创建两个 table。
示例 1
0270_001
示例1中的batch执行后,batch中的3条语句都不会执行,本例输出为:
0271_001
示例 1 的执行过程如下。第一个 INSERT 语句执行成功。然后,第二个语句导致引用完整性错误。因为这三个语句都写在 TRY 块中,异常被“抛出”并且异常处理程序启动 CATCH 块。 CATCH 回滚所有语句并打印相应的消息。之后,THROW 语句 returns 向调用者执行批处理。因此,员工 table 的内容不会更改。
注意
语句 BEGIN TRANSACTION、COMMIT TRANSACTION 和 ROLLBACK 是关于事务的 Transact-SQL 语句。这些语句分别启动、提交和回滚事务。有关这些报表和交易的一般讨论,请参见第 13 章。
这里的问题是异常是在异常处理程序之外产生的。 在定义异常处理程序之前验证发送到函数的参数。要捕获该异常,您需要围绕函数调用的异常处理程序。
如果您声明 p2 varchar(20),并保留列定义 varchar(6),您可能会得到您想要的行为,因为这样异常将在异常处理程序所涵盖的代码内部触发。