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


131

我有一个非常简单的问题,但是我没有使用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;

1
或者,您可以使用IF tablename IS NOT NULL THEN...;)
OMG Ponies

4
我正在尝试捷径...否则我必须在IF语句中编写代码,这不是唯一的EXIT语句... yi需要退出功能,而是在Stored Proc中执行多个IF。
Joe Ijam 2011年

很好的参考网址:bytes.com/topic/mysql/answers/...
Avishek

Answers:


204
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;

1
大!您甚至指出,END proc_label;不需要语法(在大多数官方MySQL示例中显示)。(这是注释掉已存储的proc的好方法,而无需滚动到底部以放置*/到位)

2
您可以离开并返回值吗?
ygaradon 2014年

35
只需将每个proc的BEGIN部分标记为'this_proc'。因为LEAVE this_proc;听起来很完美!
SNag 2014年

@ygaradon存储过程不返回值。您需要使用存储的函数return <value>返回一个值。
David Harkness 2014年

1
我认为空间是必要之间:BEGIN作为proc_label:BEGIN而给了语法错误proc_label: BEGIN的工作。
Umair Malhi

13

如果要在没有错误的情况下“提前退出”,请使用@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/zh-CN/signal.html

如何在MySQL函数中引发错误

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

附录

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

例如:

CALL AttemptedToInsertSomethingInvalid;

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


1
这感觉对我来说是最正确,最彻底的答案,而这正是我想要的。像OP一样,我需要运行多个测试(输入验证),并且我不想将它们全部嵌套,因此这对我来说效果很好。
Fodagus

12

要以一种可移植的方式处理这种情况(即,由于它不使用MySQL标签功夫,因此将在所有数据库上都可以使用),请将过程分解为逻辑部分,如下所示:

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;

7
哎呀,为什么不使用第一个解决方案呢?
Pacerier

1
希望我能投票两次。仅仅因为SQL不是一种真正的编程语言,就不能给任何借口在一个过程中编写200多个代码行。
Max Heiber,2015年

这个答案是完全错误的还是我错过了什么?为什么会有投票?显然,有一种方法可以通过公认的解决方案来证明这一点。
jlh

@jlh这错误的(现在已纠正文本),因为我不了解mysql的标签技术,但代码没有错-它实际上可以在任何DB上工作。
波希米亚

2

为什么不这样:

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

7
代码很长。。。我不能使用它。。。这只是一个示例。
Joe Ijam 2011年

无论长度如何,它都不会执行。
斯蒂芬

如果您担心缩进,只需取消if声明中的整个部分的缩进即可。从逻辑上讲,它与“早期回报”相同。
bobobobo

@bobobobo,他说在他的情况下,它使逻辑很多更有意义不是TOT重新布线解决此限制的SQL逻辑。
Pacerier

1
可能是他登录时有很多检查“ if x IS NULL THEN SETresult = -1”。您希望它真正停止做事。它降低了ifs的复杂性。少{}被淘汰
borjab 2015年

2

这对我有用:

 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

0
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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.