0

我对 MYSQL 函数和异常处理不是很熟悉。经过所有的研究,我可以在下面提出,但没有任何收获。

如果插入语句执行失败,我试图返回 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

表 - my_tbl

在此处输入图像描述

成功案例 - func1('ABC','123456')

在此处输入图像描述

例外情况 - func1('ABC','123456789')

在此处输入图像描述

编辑 -添加截图

4

3 回答 3

1

mysql 8.0.19 似乎无法捕获所有错误并正确处理它们。

错误代码:1406。第 1 行的列“p2”的数据太长

错误代码:1049。未知数据库“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 添加了退出处理程序,这是您尝试插入长文本时遇到的错误。

错误代码:1265。第 1 行的列“c2”的数据被截断

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 之前就传递了错误消息

于 2020-02-22T10:30:32.137 回答
1

这里的问题是异常是在异常处理程序之外生成的。在定义异常处理程序之前验证发送到函数的参数。要捕获该异常,您需要一个围绕函数调用的异常处理程序。

如果您声明了 p2 varchar(20),并保留了列定义 varchar(6),您可能会得到您想要的行为,因为异常会在异常处理程序覆盖的代码内触发。

于 2020-02-22T21:21:15.267 回答
0

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 语句是另一种返回机制,其行为类似于已经描述的 RAISEERROR 语句。

示例 1 显示了使用 TRY/CATCH/THROW 处理异常的工作原理。它展示了如何使用异常处理来批量插入所有语句或在发生错误时回滚整个语句组。该示例基于部门和员工表之间的引用完整性。因此,您必须使用 PRIMARY KEY 和 FOREIGN KEY 约束来创建这两个表。

例 1

0270_001

示例 1 中的批处理执行后,批处理中的所有三个语句都不会执行,该示例的输出为:

0271_001

示例 1 的执行工作如下。第一个 INSERT 语句执行成功。然后,第二条语句导致参照完整性错误。因为所有三个语句都写在 TRY 块内,所以“抛出”异常并且异常处理程序启动 CATCH 块。CATCH 回滚所有语句并打印相应的消息。之后,THROW 语句将批处理的执行返回给调用者。因此,员工表的内容不会改变。

笔记

BEGIN TRANSACTION、COMMIT TRANSACTION 和 ROLLBACK 语句是有关事务的 Transact-SQL 语句。这些语句分别启动、提交和回滚事务。有关这些报表和交易的一般讨论,请参见第 13 章。

于 2020-02-22T17:56:47.453 回答