Mysql - Как выйти / выйти из хранимой процедуры

131

У меня очень простой вопрос, но я не получил простого кода для выхода из SP с помощью Mysql. Кто-нибудь может поделиться со мной, как это сделать?

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 нужна функция выхода, вместо этого мы выполняем несколько IF внутри Stored Proc.
Joe Ijam 07
Хороший ссылочный URL: bytes.com/topic/mysql/answers/…
Avishek,

Ответы:

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;
piotrm
источник
1
Большой! Вы даже указываете, что END proc_label;синтаксис (показанный в большинстве официальных примеров MySQL) не нужен. (это отличный способ закомментировать сохраненный процесс без необходимости прокручивать вниз, чтобы вставить его */на место)
2
вы можете оставить и вернуть значение?
ygaradon 08
35
Просто пометьте раздел BEGIN каждой процедуры «this_proc». Потому что LEAVE this_proc;звучит идеально!
SNag 01
@ygaradon Хранимые процедуры не возвращают значений. Вам нужно использовать сохраненную функцию и return <value>вернуть значение.
Дэвид Харкнесс
1
Я думаю, что необходимо пространство между :и, так BEGINкак proc_label:BEGINдал синтаксическую ошибку во время работы proc_label: BEGIN.
Умайр Малхи, 09
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/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;

Обратите внимание, что когда вы создаете процедуру, для таких вещей не выполняется проверка. Таким образом, хотя в чем-то вроде скомпилированного языка вы никогда не сможете вызвать функцию, которой не было, в таком сценарии она просто выйдет из строя во время выполнения, что именно то, что нужно в данном случае!

BuvinJ
источник
1
Мне кажется, это самый правильный и исчерпывающий ответ, и это именно то, что я хотел. Как и у OP, у меня есть несколько тестов (проверка ввода), которые мне нужно запустить, и я не хотел вкладывать их все, так что это хорошо работает для меня.
Fodagus
12

Чтобы справиться с этой ситуацией портативным способом (то есть будет работать со всеми базами данных, потому что он не использует метку 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;
Богемский
источник
7
Юкс, почему бы вместо этого не использовать первое решение?
Pacerier 01
1
Хотел бы я проголосовать за это дважды. Тот факт, что SQL не является настоящим языком программирования, не дает никому оправдания для написания 200+ строк кода в одной процедуре.
Макс Хейбер
Это просто неправильный ответ или я что-то упустил? Почему у него есть положительные голоса? Очевидно, что есть способ добиться этого, о чем свидетельствует принятое решение.
jlh
@jlh это было неправильно (текст теперь исправлен) в том смысле, что я не знал о технике меток mysql, но код не ошибочен - он будет работать на любой БД.
Bohemian
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 07
Независимо от длины, он не будет выполнен.
Стивен
Если вас беспокоит отступ, просто уберите отступ во всем разделе в ifинструкции. Это логически идентично «раннему возврату».
bobobobo 06
@bobobobo, он говорит, что в его случае логически гораздо больше смысла не перестраивать логику вокруг этого ограничения sql.
Pacerier 01
1
Может быть, у него есть логин с множеством проверок «если x IS NULL THEN SETresult = -1». Вы хотите, чтобы он ДЕЙСТВИТЕЛЬНО перестал что-то делать. Это снижает сложность ifs. Менее {} аннидировано
Borjab
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;
sdfor
источник