Mysql - 如何从存储过程中退出/退出

Posted

技术标签:

【中文标题】Mysql - 如何从存储过程中退出/退出【英文标题】:Mysql - How to quit/exit from stored procedure 【发布时间】:2011-09-09 18:00:09 【问题描述】:

我有一个非常简单的问题,但我没有得到任何简单的代码来使用 mysql 从 SP 中退出。 谁能和我分享一下如何做到这一点?

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NULL THEN
          #Exit this stored procedure here
     END IF;

     #proceed the code
END;

【问题讨论】:

或者,你可以使用IF tablename IS NOT NULL THEN ... ;) 我正在尝试简化捷径...否则我必须在 IF 语句中编写代码,这不是唯一的 EXIT 语句...您需要退出函数而不是我们在内部执行多个 IF存储过程 好参考网址:bytes.com/topic/mysql/answers/… 【参考方案1】:
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
proc_label:BEGIN
     IF tablename IS NULL THEN
          LEAVE proc_label;
     END IF;

     #proceed the code
END;

【讨论】:

太棒了!您甚至指出不需要 END proc_label; 语法(在大多数官方 MySQL 示例中显示)。 (这是注释掉存储过程的好方法,无需滚动到底部即可将*/ 放置到位) 能不能留下并返回一个值? 只需标记每个 proc 'this_proc' 的 BEGIN 部​​分。因为LEAVE this_proc; 听起来很完美! @David Harkness 他不能将它传递给 out 参数吗?那不是返回值吗? 我认为:BEGIN 之间需要空格,因为proc_label:BEGINproc_label: BEGIN 工作时给出了语法错误。【参考方案2】:

如果您希望在没有错误的情况下“提前退出”,请使用@piotrm 发布的已接受答案。然而,最常见的情况是,您会因错误情况而放弃(尤其是在 SQL 过程中)。

从 MySQL v5.5 开始,您可以抛出异常。否定异常处理程序等将获得相同结果,但以更简洁、更精确的方式。

方法如下:

DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';

IF <Some Error Condition> THEN      
    SIGNAL CUSTOM_EXCEPTION
    SET MESSAGE_TEXT = 'Your Custom Error Message';
END IF;     

注意SQLSTATE '45000' 等同于“未处理的用户定义的异常条件”。默认情况下,这将产生一个错误代码1644(具有相同的含义)。请注意,您可以根据需要抛出其他条件代码或错误代码(以及异常处理的其他详细信息)。

有关此主题的更多信息,请查看:

https://dev.mysql.com/doc/refman/5.5/en/signal.html

How to raise an error within a MySQL function

http://www.databasejournal.com/features/mysql/mysql-error-handling-using-the-signal-and-resignal-statements.html

附录

当我重新阅读我的这篇文章时,我意识到我还有一些额外的东西要补充。在 MySQL v5.5 之前,有一种方法可以模拟抛出异常。这不完全是一回事,但这是类似的:通过调用不存在的过程来创建错误。用有意义的名称调用过程,以便获得确定问题所在的有用方法。当错误发生时,您将看到失败的路线(取决于您的执行上下文)。

例如:

CALL AttemptedToInsertSomethingInvalid;

请注意,当您创建过程时,不会对此类内容执行验证。因此,虽然在编译语言之类的语言中,您永远无法调用不存在的函数,但在这样的脚本中,它只会在运行时失败,这正是这种情况下所需要的!

【讨论】:

这对我来说是最正确、最彻底的答案,也正是我想要的。像 OP 一样,我有几个测试(输入验证)需要运行,我不想将它们全部嵌套,所以这对我来说很有效。【参考方案3】:

要以可移植的方式处理这种情况(即所有数据库都可以工作,因为它不使用 MySQL 标签 Kung fu),请将过程分解为逻辑部分,如下所示:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
         CALL SP_Reporting_2(tablename);
     END IF;
END;

CREATE PROCEDURE SP_Reporting_2(IN tablename VARCHAR(20))
BEGIN
     #proceed with code
END;

【讨论】:

糟糕,为什么不使用第一个解决方案呢? 希望我能投票两次。不能仅仅因为 SQL 不是真正的编程语言,就可以让任何人有理由在一个过程中编写 200 多行代码。 这个答案是完全错误的还是我遗漏了什么?为什么它有赞成票?显然,有一种方法可以实现这一点,这一点已被公认的解决方案证明。 @jlh 它 错误(现在更正了文本),因为我不知道 mysql 的标签技术,但代码没有错 - 它可以正常工作实际上任何数据库。【参考方案4】:

这对我有用:

 CREATE DEFINER=`root`@`%` PROCEDURE `save_package_as_template`( IN package_id int , 
IN bus_fun_temp_id int  , OUT o_message VARCHAR (50) ,
            OUT o_number INT )
 BEGIN

DECLARE  v_pkg_name  varchar(50) ;

DECLARE  v_pkg_temp_id  int(10)  ; 

DECLARE  v_workflow_count INT(10);

-- checking if workflow created for package
select count(*)  INTO v_workflow_count from workflow w where w.package_id = 
package_id ;

this_proc:BEGIN   -- this_proc block start here 

 IF  v_workflow_count = 0 THEN
   select 'no work flow ' as 'workflow_status' ;
    SET o_message ='Work flow is not created for this package.';
    SET  o_number = -2 ;
      LEAVE this_proc;
 END IF;

select 'work flow  created ' as 'workflow_status' ;
-- To  send some message
SET o_message ='SUCCESSFUL';
SET  o_number = 1 ;

  END ;-- this_proc block end here 

END

【讨论】:

【参考方案5】:

为什么不这样:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
          #proceed the code
     END IF;
     # Do nothing otherwise
END;

【讨论】:

代码很长...我不能用这个...这只是一个示例。 不管长短都不执行。 如果您担心缩进,只需取消缩进 if 语句中的整个部分。这在逻辑上等同于“提前回归”。 @bobobobo,他说在他的情况下,不围绕这个 sql 限制重新连接逻辑在逻辑上更有意义。 可能是他登录时有很多检查“如果 x 为 NULL THEN SETresult = -1”。你希望它真的停止做事。它降低了ifs的复杂性。更少被淘汰【参考方案6】:
MainLabel:BEGIN

IF (<condition>) IS NOT NULL THEN
    LEAVE MainLabel;
END IF; 

....code

i.e.
IF (@skipMe) IS NOT NULL THEN /* @skipMe returns Null if never set or set to NULL */
     LEAVE MainLabel;
END IF;

【讨论】:

【参考方案7】:

如果您以后可以测试错误字段的值,我认为这个解决方案很方便。这也适用于创建临时表并返回错误列表。

DROP PROCEDURE IF EXISTS $procName;
DELIMITER //
CREATE PROCEDURE $procName($params)
BEGIN
    DECLARE error INT DEFAULT 0;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET error = 1;
    SELECT
       $fields
    FROM $tables
    WHERE $where
    ORDER BY $sorting LIMIT 1
    INTO $vars;
    IF error = 0 THEN
       SELECT $vars;
    ELSE
       SELECT 1 AS error;
       SET @error = 0;
    END IF;
END//
CALL $procName($effp);

【讨论】:

以上是关于Mysql - 如何从存储过程中退出/退出的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 存储过程错误处理

MySQL存储过程——一一检查是不是满足某些条件;如果不满足,则退出程序并返回特定消息

如何停止在 MySQL 中执行完整的存储过程?

HSQLDB:退出存储过程

关于MySQL存储过程异常处理的一点心得

oracle存储过程中如何对一个变量累加赋值 最好有个例子