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

问题描述 投票:0回答:8

我有一个非常简单的问题,但我没有得到任何简单的代码来使用 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;
mysql sql stored-procedures
8个回答
252
投票
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;

24
投票

如果您希望在没有错误的情况下“提前退出”,请使用@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

如何在 MySQL 函数中引发错误

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

附录

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

例如:

CALL AttemptedToInsertSomethingInvalid;

请注意,当您创建过程时,不会对此类事物执行验证。因此,虽然在编译语言之类的东西中,您永远无法调用不存在的函数,在这样的脚本中,它只会在运行时失败,这正是本例中所期望的!


15
投票

要以可移植的方式处理这种情况(即适用于所有数据库,因为它不使用 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;

5
投票

这对我有用:

 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

3
投票

为什么不是这个:

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

1
投票
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;

0
投票

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

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

0
投票

如果需要返回语句,可以使用 FUNCTION:

delimiter //
create FUNCTION SP_Reporting(IN tablename VARCHAR(20))
reads sql data
returns int
begin
  if tablename is null then
    return 0; -- returns work from stored procs
  end if;
  
  -- other code path
  return 1;
end;
delimiter ;

可能比其他建议更简洁,只是将应该返回的情况留在

if
语句之外:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
          -- Run the code here
     END IF;
     -- Code failing the above if statement will end up here
END;
© www.soinside.com 2019 - 2024. All rights reserved.