การจัดการข้อยกเว้นใน Oracle PL/SQL (ตัวอย่าง)
การจัดการข้อยกเว้นใน PL/SQL คืออะไร
ข้อยกเว้นเกิดขึ้นเมื่อกลไก PL/SQL พบคำสั่งที่ไม่สามารถดำเนินการได้เนื่องจากข้อผิดพลาดที่เกิดขึ้นขณะรันไทม์ ข้อผิดพลาดเหล่านี้จะไม่ถูกบันทึกในขณะที่ทำการคอมไพล์ และด้วยเหตุนี้ ข้อผิดพลาดเหล่านี้จึงจำเป็นต้องจัดการเฉพาะในขณะรันไทม์เท่านั้น
ตัวอย่างเช่น หากกลไก PL/SQL ได้รับคำสั่งให้หารตัวเลขใดๆ ด้วย '0' กลไก PL/SQL จะส่งค่านั้นเป็นข้อยกเว้น ข้อยกเว้นจะเกิดขึ้นในเวลารันไทม์โดยกลไก PL/SQL เท่านั้น
ข้อยกเว้นจะทำให้โปรแกรมไม่สามารถดำเนินการต่อไปได้ ดังนั้นเพื่อหลีกเลี่ยงสภาวะดังกล่าว จึงต้องบันทึกและจัดการแยกกัน กระบวนการนี้เรียกว่าเป็น Exception-Handling ซึ่งโปรแกรมเมอร์จะจัดการข้อยกเว้นที่อาจเกิดขึ้นในขณะรันไทม์
ไวยากรณ์การจัดการข้อยกเว้น
ข้อยกเว้นจะได้รับการจัดการที่บล็อก ระดับ เช่น เมื่อมีข้อยกเว้นใดๆ เกิดขึ้นในบล็อกใดๆ การควบคุมจะออกมาจากการดำเนินการส่วนหนึ่งของบล็อกนั้น ข้อยกเว้นจะถูกจัดการที่ส่วนการจัดการข้อยกเว้นของบล็อกนั้น หลังจากจัดการข้อยกเว้นแล้ว ไม่สามารถส่งการควบคุมกลับไปยังส่วนการดำเนินการของบล็อกนั้นอีกครั้งได้
ไวยากรณ์ด้านล่างอธิบายวิธีการจับและจัดการกับข้อยกเว้น
BEGIN <execution block> . . EXCEPTION WHEN <exceptionl_name> THEN <Exception handling code for the “exception 1 _name’' > WHEN OTHERS THEN <Default exception handling code for all exceptions > END;
คำอธิบายไวยากรณ์:
- ในรูปแบบข้างต้น บล็อกการจัดการข้อยกเว้นประกอบด้วยชุดของเงื่อนไข WHEN ที่จะจัดการข้อยกเว้น
- แต่ละเงื่อนไข WHEN ตามด้วยชื่อข้อยกเว้นซึ่งคาดว่าจะถูกยกขึ้นในขณะรันไทม์
- เมื่อมีการหยิบยกข้อยกเว้นใดๆ ขึ้นในขณะรันไทม์ กลไก PL/SQL จะดูในส่วนการจัดการข้อยกเว้นสำหรับข้อยกเว้นนั้นๆ โดยจะเริ่มต้นจากส่วนคำสั่ง 'WHEN' แรก และจะค้นหาตามลำดับ
- หากพบการจัดการข้อยกเว้นสำหรับข้อยกเว้นที่ได้รับการหยิบยกขึ้นมา ระบบจะดำเนินการในส่วนของโค้ดการจัดการนั้นโดยเฉพาะ
- หากไม่มีส่วนคำสั่ง 'WHEN' ใดปรากฏสำหรับข้อยกเว้นที่ได้รับการยกขึ้น กลไก PL/SQL จะดำเนินการส่วน 'WHEN OTHERS' (ถ้ามี) นี่เป็นเรื่องปกติสำหรับข้อยกเว้นทั้งหมด
- หลังจากดำเนินการข้อยกเว้น การควบคุมชิ้นส่วนจะออกจากบล็อกปัจจุบัน
- สามารถดำเนินการส่วนข้อยกเว้นได้เพียงส่วนเดียวสำหรับบล็อกในขณะรันไทม์ หลังจากดำเนินการแล้ว คอนโทรลเลอร์จะข้ามส่วนการจัดการข้อยกเว้นที่เหลือ และจะออกจากบล็อกปัจจุบัน
หมายเหตุ เมื่อคนอื่นควรอยู่ที่ตำแหน่งสุดท้ายของลำดับเสมอ ส่วนการจัดการข้อยกเว้นปรากฏหลังจาก WHEN OTHERS จะไม่ถูกดำเนินการ เนื่องจากการควบคุมจะออกจากบล็อกหลังจากดำเนินการ WHEN OTHERS
ประเภทของข้อยกเว้น
ข้อยกเว้นมีอยู่ 2 ประเภท กรุณา/SQL.
- ข้อยกเว้นที่กำหนดไว้ล่วงหน้า
- ข้อยกเว้นที่ผู้ใช้กำหนด
ข้อยกเว้นที่กำหนดไว้ล่วงหน้า
Oracle ได้กำหนดข้อยกเว้นทั่วไปไว้ล่วงหน้าแล้ว ข้อยกเว้นเหล่านี้มีชื่อข้อยกเว้นเฉพาะและหมายเลขข้อผิดพลาด ข้อยกเว้นเหล่านี้ถูกกำหนดไว้แล้วในแพ็คเกจ 'มาตรฐาน' Oracle- ในโค้ด เราสามารถใช้ชื่อข้อยกเว้นที่กำหนดไว้ล่วงหน้าเหล่านี้เพื่อจัดการได้โดยตรง
ด้านล่างนี้คือข้อยกเว้นบางประการที่กำหนดไว้ล่วงหน้า
ข้อยกเว้น | รหัสผิดพลาด | เหตุผลข้อยกเว้น |
---|---|---|
ACCESS_INTO_NULL | ออร่า-06530 | กำหนดค่าให้กับคุณลักษณะของวัตถุที่ไม่ได้เตรียมใช้งาน |
CASE_NOT_FOUND | ออร่า-06592 | ไม่ตรงตามเงื่อนไขประโยค 'WHEN' ในคำสั่ง CASE และไม่มีการระบุประโยค 'ELSE' |
คอลเลกชัน_IS_NULL | ออร่า-06531 | การใช้วิธีการรวบรวม (ยกเว้นที่มีอยู่) หรือการเข้าถึงคุณลักษณะการรวบรวมในคอลเลกชันที่ไม่ได้กำหนดค่าเริ่มต้น |
CURSOR_ALREADY_OPEN | ออร่า-06511 | กำลังพยายามเปิดก เคอร์เซอร์ ซึ่งเปิดอยู่แล้ว |
DUP_VAL_ON_INDEX | ออร่า-00001 | การจัดเก็บค่าที่ซ้ำกันในคอลัมน์ฐานข้อมูลที่ถูกจำกัดโดยดัชนีเฉพาะ |
INVALID_CURSOR | ออร่า-01001 | การใช้งานเคอร์เซอร์ที่ผิดกฎหมาย เช่น การปิดเคอร์เซอร์ที่ไม่ได้เปิด |
INVALID_NUMBER | ออร่า-01722 | การแปลงอักขระเป็นตัวเลขล้มเหลวเนื่องจากอักขระตัวเลขไม่ถูกต้อง |
ไม่พบข้อมูล | ออร่า-01403 | เมื่อคำสั่ง 'SELECT' ที่มี INTO clause ไม่ดึงข้อมูลแถว |
ROW_ไม่ตรงกัน | ออร่า-06504 | เมื่อชนิดข้อมูลตัวแปรเคอร์เซอร์เข้ากันไม่ได้กับชนิดการส่งคืนเคอร์เซอร์จริง |
SUBSCRIPT_BEYOND_COUNT | ออร่า-06533 | อ้างอิงคอลเลกชันตามหมายเลขดัชนีที่ใหญ่กว่าขนาดคอลเลกชัน |
SUBSCRIPT_OUTSIDE_LIMIT | ออร่า-06532 | การอ้างอิงคอลเลกชันตามหมายเลขดัชนีที่อยู่นอกช่วงที่กฎหมายกำหนด (เช่น: -1) |
TOO_MANY_ROWS | ออร่า-01422 | เมื่อคำสั่ง 'SELECT' พร้อมด้วย INTO clause ส่งคืนมากกว่าหนึ่งแถว |
VALUE_ERROR | ออร่า-06502 | ข้อผิดพลาดทางคณิตศาสตร์หรือข้อจำกัดด้านขนาด (เช่น การกำหนดค่าให้กับตัวแปรที่มีขนาดใหญ่กว่าขนาดของตัวแปร) |
ศูนย์_DIVIDE | ออร่า-01476 | การหารตัวเลขด้วย '0' |
ข้อยกเว้นที่ผู้ใช้กำหนด
In Oracleนอกเหนือจากข้อยกเว้นที่กำหนดไว้ล่วงหน้าแล้ว โปรแกรมเมอร์สามารถสร้างข้อยกเว้นของตนเองและจัดการได้ สามารถสร้างได้ในระดับโปรแกรมย่อยในส่วนการประกาศ ข้อยกเว้นเหล่านี้จะมองเห็นได้เฉพาะในโปรแกรมย่อยนั้นเท่านั้น ข้อยกเว้นที่กำหนดไว้ในข้อกำหนดเฉพาะของแพ็คเกจคือข้อยกเว้นสาธารณะ และสามารถมองเห็นได้ทุกที่ที่สามารถเข้าถึงแพ็คเกจได้
ไวยากรณ์: ในระดับโปรแกรมย่อย
DECLARE <exception_name> EXCEPTION; BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> END;
- ในรูปแบบข้างต้น ตัวแปร 'Exception_name' ถูกกำหนดให้เป็นประเภท 'EXCEPTION'
- สามารถใช้ในลักษณะเดียวกันกับข้อยกเว้นที่กำหนดไว้ล่วงหน้า
ไวยากรณ์:ที่ระดับข้อกำหนดแพ็คเกจ
CREATE PACKAGE <package_name> IS <exception_name> EXCEPTION; . . END <package_name>;
- ในไวยากรณ์ข้างต้น ตัวแปร 'Exception_name' ถูกกำหนดให้เป็นประเภท 'EXCEPTION' ในข้อกำหนดแพ็คเกจของ -
- สามารถใช้ในฐานข้อมูลได้ทุกที่ที่สามารถเรียกแพ็คเกจ 'package_name' ได้
PL/SQL เพิ่มข้อยกเว้น
ข้อยกเว้นที่กำหนดไว้ล่วงหน้าทั้งหมดจะถูกยกขึ้นโดยปริยายทุกครั้งที่เกิดข้อผิดพลาด แต่จำเป็นต้องยกข้อยกเว้นที่ผู้ใช้กำหนดไว้อย่างชัดเจน ซึ่งสามารถทำได้โดยใช้คำหลัก 'RAISE' สามารถใช้ในลักษณะใดก็ได้ที่กล่าวถึงด้านล่าง
หากใช้ 'RAISE' แยกต่างหากในโปรแกรม มันจะเผยแพร่ข้อยกเว้นที่เกิดขึ้นแล้วไปยังบล็อกหลัก เฉพาะในบล็อกข้อยกเว้นเท่านั้นที่สามารถใช้ได้ดังที่แสดงด้านล่าง
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> RAISE; END;
คำอธิบายไวยากรณ์:
- ในรูปแบบข้างต้น คำหลัก RAISE ถูกใช้ในบล็อกการจัดการข้อยกเว้น
- เมื่อใดก็ตามที่โปรแกรมพบข้อยกเว้น “Exception_name” ข้อยกเว้นจะถูกจัดการและจะดำเนินการให้เสร็จสิ้นตามปกติ
- แต่คีย์เวิร์ด 'RAISE' ในส่วนการจัดการข้อยกเว้นจะเผยแพร่ข้อยกเว้นนี้ไปยังโปรแกรมหลัก
หมายเหตุ ในขณะที่เพิ่มข้อยกเว้นให้กับบล็อกหลัก ข้อยกเว้นที่กำลังถูกเพิ่มควรจะมองเห็นได้ที่บล็อกหลักด้วย มิฉะนั้น Oracle จะแสดงข้อผิดพลาด
- เราสามารถใช้คำหลัก 'RAISE' ตามด้วยชื่อข้อยกเว้นเพื่อเพิ่มข้อยกเว้นที่ผู้ใช้กำหนด/กำหนดไว้ล่วงหน้านั้น สามารถใช้ได้ทั้งในส่วนการดำเนินการและในส่วนการจัดการข้อยกเว้นเพื่อเพิ่มข้อยกเว้น
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> RAISE <exception_name> EXCEPTION WHEN <exception_name> THEN <Handler> END;
คำอธิบายไวยากรณ์:
- ในรูปแบบข้างต้น คำหลัก RAISE จะถูกใช้ในส่วนการดำเนินการตามด้วยข้อยกเว้น “Exception_name”
- สิ่งนี้จะทำให้เกิดข้อยกเว้นเฉพาะนี้ในขณะที่ดำเนินการ และจำเป็นต้องได้รับการจัดการหรือหยิบยกเพิ่มเติม
1 ตัวอย่าง: ในตัวอย่างนี้เราจะมาดูกัน
- วิธีการประกาศข้อยกเว้น
- วิธีการยกข้อยกเว้นที่ประกาศไว้และ
- วิธีเผยแพร่ไปยังบล็อกหลัก
DECLARE Sample_exception EXCEPTION; PROCEDURE nested_block IS BEGIN Dbms_output.put_line(‘Inside nested block’); Dbms_output.put_line(‘Raising sample_exception from nested block’); RAISE sample_exception; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line (‘Exception captured in nested block. Raising to main block’); RAISE, END; BEGIN Dbms_output.put_line(‘Inside main block’); Dbms_output.put_line(‘Calling nested block’); Nested_block; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line (‘Exception captured in main block'); END: /
คำอธิบายรหัส:
- รหัสบรรทัดที่ 2: ประกาศตัวแปร 'sample_Exception' เป็นประเภท EXCEPTION
- รหัสบรรทัดที่ 3: ประกาศขั้นตอน Nested_block
- รหัสบรรทัดที่ 6: พิมพ์ข้อความ “Inside Nested Block”
- รหัสบรรทัด 7: การพิมพ์คำสั่ง “Raising Sample_Exceptionion from Nested Block”
- รหัสบรรทัด 8: เพิ่มข้อยกเว้นโดยใช้ 'RAISE Sample_Exception'
- รหัสบรรทัด 10: ตัวจัดการข้อยกเว้นสำหรับข้อยกเว้น Sample_Exception ในบล็อกที่ซ้อนกัน
- รหัสบรรทัด 11: การพิมพ์คำสั่ง 'ข้อยกเว้นถูกบันทึกในบล็อกที่ซ้อนกัน' ขึ้นสู่บล็อกหลัก'
- รหัสบรรทัด 12: เพิ่มข้อยกเว้นให้กับบล็อกหลัก (เผยแพร่ไปยังบล็อกหลัก)
- รหัสบรรทัด 15: พิมพ์ข้อความ “ภายในบล็อกหลัก”
- รหัสบรรทัด 16: การพิมพ์คำสั่ง "การเรียกบล็อกที่ซ้อนกัน"
- รหัสบรรทัด 17: การเรียกขั้นตอน Nested_block
- รหัสบรรทัด 18: ข้อยกเว้น
- รหัสบรรทัด 19: ตัวจัดการข้อยกเว้นสำหรับ Sample_Exception ในบล็อกหลัก
- รหัสบรรทัด 20: การพิมพ์คำสั่ง “ข้อยกเว้นถูกบันทึกในบล็อกหลัก”
ประเด็นสำคัญที่ควรทราบในข้อยกเว้น
- ในฟังก์ชัน ข้อยกเว้นควรคืนค่าหรือเพิ่มข้อยกเว้นเพิ่มเติมเสมอ อื่น Oracle จะส่งข้อผิดพลาด 'ฟังก์ชันส่งคืนโดยไม่มีค่า' ขณะรันไทม์
- สามารถกำหนดคำสั่งควบคุมธุรกรรมได้ที่บล็อกการจัดการข้อยกเว้น
- SQLERRM และ SQLCODE เป็นฟังก์ชันในตัวที่จะให้ข้อความและโค้ดข้อยกเว้น
- หากไม่มีการจัดการข้อยกเว้น ตามค่าเริ่มต้น ธุรกรรมที่ใช้งานอยู่ในเซสชันนั้นจะถูกย้อนกลับ
- RAISE_APPLICATION_ERROR (- - ) สามารถใช้แทน RAISE เพื่อเพิ่มข้อผิดพลาดด้วยรหัสผู้ใช้และข้อความ รหัสข้อผิดพลาดควรมากกว่า 20000 และนำหน้าด้วย '-'
สรุป
หลังจากบทนี้แล้ว คุณควรจะสามารถทำงานในด้านต่อไปนี้ของ Pl ได้ SQL ข้อยกเว้น
- การจัดการกับข้อยกเว้น
- กำหนดข้อยกเว้น
- ยกข้อยกเว้น
- การแพร่กระจายข้อยกเว้น