content top
קינון Try & Catch

קינון Try & Catch

(כותרת משנה: “מה מצאתי ולא ידעתי”)

לא ידעתי שניתן לקנן פקודות Try & Catch, וגיליתי זאת בעקבות בעייה שהונחה היום לפיתחי:

פרוצדורה מורכבת כוללת Try & Catch, ובמהלכה מופעלת פרוצדורה משנית שהצלחתה אינה חיונית להמשך הריצה. בדרך כלל כשיש תקלה – הריצה מופנית לבלוק ה-Catch, אך במקרה של אותה פרוצדורה משנית – אפשר לדלג הלאה באלגנטיות.. הפתרון הוא ליצור Try & Catch מקונן סביב הפרוצדורה הנ”ל מבלי להפעיל דבר ב-Catch.

דוגמה איך זה נראה:

Begin Try

Print '1 Try Begin';

    Begin Try

    Print '2 Try Begin';

    Print '2 Try End';

    End Try

    Begin Catch

    Print '2 Catch';

    End Catch

Print '1 Try End';

End Try

Begin Catch

Print '1 Catch';

End Catch

image

הקוד תקין: מתחיל את 1, מתחיל את 2 (המקונן), מסיים את 2, מסיים את 1.

כעת נציב פקודה שגוייה (חלוקה ב-0) בתוך הבלוק המקונן:

Begin Try

Print '1 Try Begin';

    Begin Try

    Print '2 Try Begin';

    Print 2/0;

    Print '2 Try End';

    End Try

    Begin Catch

    Print '2 Catch';

    End Catch

Print '1 Try End';

End Try

Begin Catch

Print '1 Catch';

End Catch

image

1 התחיל, 2 התחיל, 2 נפל בגלל שגיאה ומופיעה הודעה מה-Catch המקונן, 1 הסתיים (כלומר- מה-Catch המקונן הריצה המשיכה ל-Try הראשון).

כמובן שניתן במקרה הצורך לבצע קינון נוסף.

דוגמה שימושית אחרת היא בלוק ה-Catch: מקרה טיפוסי הוא זה ששומר את פרטי השגיאה בטבלת לוג-שגיאות לצורך תיעוד, טיפול ומעקב בהמשך. מה קורה כשכתיבה לטבלה זו נופלת בגלל בעייה בלתי צפוייה? ניתן לקנן בתוך ה-Catch מבנה של Try & Catch פנימי.

נתחיל מהמקרה הפשוט:

Begin Try

Print '1 Try Begin';

Print 1/0;

Print '1 Try End';

End Try

Begin Catch

Print '1 Catch Begin';

Print '1 Catch End';

End Catch

image

ה-Try התחיל, שגיאת החלוקה ב-0 מעבירה אותנו ל-Catch שמתחיל ומסתיים.

מה קורה אם ב-Catch עצמו צצה שגיאה?

Begin Try

Print '1 Try Begin';

Print 1/0;

Print '1 Try End';

End Try

Begin Catch

Print '1 Catch Begin';

Print 1/0;

Print '1 Catch End';

End Catch

image

במקרה זה נזרקת הודעת שגיאה, אך הריצה נמשכת וה-Catch מסתיים.

הסיבה שהריצה נמשכת היא מפני שכברירת מחדל – הגדרת ה-Xact_Abort של המערכת היא Off, אך אם נגדיר אותה במפורק Set Xact_Abort On הריצה תיעצר בשגיאה.

בכל מקרה- את הפקודה הבעייתית ניתן “לעטוף” ב-Try & Catch מקונן כך:

Begin Try

Print '1 Try Begin';

Print 1/0;

Print '1 Try End';

End Try

Begin Catch

Print '1 Catch Begin';

    Begin Try

    Print '2 Try Begin';

    Print 1/0;

    Print '2 Try End';

    End Try

    Begin Catch

    Print '2 Catch Begin';

    Print '2 Catch End';

    End Catch

Print '1 Catch End';

End Catch

image

ה-Try הראשון התחיל, בשל השגיאה הריצה עוברת ל-Catch החיצוני שמתחיל, בתוכו מתחיל ה-Try הפנימי המקונן, בשל השגיאה בו – הריצה עובדת ל-Catch הפנימי המקונן שמתחיל ומסתיים, ולבסוף גם ה-Catch החיצוני מסתיים.

כמובן שכאן אפשר להתחכם ולשאול מה קורה אם יש שגיאה ב-Catch המקונן, האם ליצור קינון עמוק יותר (שגם הוא עצמו עלול ליפול)? אני סומך על ה-DBA האינטליגנט שיקפיד לכלול ב-Catch המקונן פקודות יציבות ששום תסריט ריאלי לא יפיל אותן.. כלומר- ה-Catch החיצוני יטפל ב-“שגיאות בלתי צפויות הצפויות לקרות” והפנימי ב-“שגיאות בלתי צפויות שאינן צפויות לקרות”..


כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

3 × one =