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 เท่านั้น ... ที่ยี่ต้องการฟังก์ชัน exit แทนเราทำ IF หลายตัวใน Stored Proc
Joe Ijam

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;

1
ที่ดี! คุณยังชี้ให้เห็นว่าEND proc_label;ไม่จำเป็นต้องใช้ไวยากรณ์ (แสดงในตัวอย่าง MySQL ที่เป็นทางการส่วนใหญ่) (นี่เป็นวิธีที่ยอดเยี่ยมในการแสดงความคิดเห็นเกี่ยวกับ proc ที่เก็บไว้โดยไม่ต้องเลื่อนไปด้านล่างเพื่อวาง*/)

2
คุณสามารถออกและคืนค่าได้หรือไม่?
ygaradon

35
เพียงติดป้ายกำกับส่วน BEGIN ของทุก proc "this_proc" LEAVE this_proc;เสียงเพราะเป๊ะ!
SNag

@ygaradon เก็บไว้ขั้นตอนการไม่คืนค่า คุณต้องใช้ฟังก์ชันที่จัดเก็บไว้และreturn <value>เพื่อส่งคืนค่า
David Harkness

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

โปรดทราบว่าเมื่อคุณสร้างโพรซีเดอร์จะไม่มีการตรวจสอบความถูกต้องในสิ่งดังกล่าว ดังนั้นในบางสิ่งเช่นภาษาคอมไพล์คุณไม่สามารถเรียกใช้ฟังก์ชันที่ไม่มีอยู่ในสคริปต์เช่นนี้มันจะล้มเหลวในรันไทม์ซึ่งเป็นสิ่งที่ต้องการในกรณีนี้!


1
นี่เป็นคำตอบที่ถูกต้องและละเอียดถี่ถ้วนที่สุดสำหรับฉันและเป็นสิ่งที่ฉันต้องการ เช่นเดียวกับ OP ฉันมีการทดสอบหลายครั้ง (การตรวจสอบอินพุต) ฉันต้องเรียกใช้และฉันไม่ต้องการซ้อนทั้งหมดดังนั้นสิ่งนี้จึงใช้ได้ดีสำหรับฉัน
Fodagus

12

ในการจัดการสถานการณ์นี้แบบพกพา (กล่าวคือจะทำงานบนฐานข้อมูลทั้งหมดเนื่องจากไม่ใช้ MySQL label 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
Yucks ทำไมไม่ใช้วิธีแก้ปัญหาแรกแทน?
Pacerier

1
หวังว่าฉันจะโหวตได้สองครั้ง เพียงเพราะ SQL ไม่ใช่ภาษาโปรแกรมจริงไม่ได้ให้ข้ออ้างกับใครในการเขียนโค้ดมากกว่า 200 บรรทัดในขั้นตอนเดียว
Max Heiber

คำตอบนี้ผิดธรรมดาหรือฉันขาดอะไรไป? ทำไมจึงมีการโหวตเพิ่ม เห็นได้ชัดว่ามีวิธีที่จะบรรลุสิ่งนี้ซึ่งแสดงให้เห็นโดยวิธีแก้ปัญหาที่ได้รับการยอมรับ
jlh

@jlh มันก็ไม่ถูกต้อง (ข้อความแก้ไขตอนนี้) ในการที่ฉันไม่ได้รู้เกี่ยวกับเทคนิคฉลากของ MySQL แต่รหัสไม่ผิด - มันจะทำงานบนฐานข้อมูลใด ๆ จริง
โบฮีเมียน

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

ไม่ว่าจะมีความยาวเท่าใดก็จะไม่ดำเนินการ
Stephen

หากคุณกังวลเกี่ยวกับการเยื้องเพียงแค่คลายการเยื้องส่วนทั้งหมดในifคำสั่ง มันมีเหตุผลเหมือนกับ "ผลตอบแทนก่อนกำหนด"
bobobobo

@bobobobo เขาพูดในกรณีของเขาว่ามันสมเหตุสมผลกว่ามากที่จะไม่ rewire ตรรกะเกี่ยวกับข้อ จำกัด sql นี้
Pacerier

1
อาจเป็นเขามีล็อกอินที่มีการตรวจสอบจำนวนมาก "if 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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.