מדריך T-SQL: יציאה ודילוג בתוך לולאות

הדוגמאות בפוסט הזה מתייחסות לבסיס נתונים המבוסס על הסדרה הפופולארית "משחקי הכס" שיצרתי במיוחד עבור המדריך הזה. אם אתם רוצים להוריד אותו בעצמכם או סתם להבין מה זה בכלל אתם יכולים ללחוץ כאן

בפוסט הקודם הסברתי מהן לולאה ואיך כותבים אותן. לעיתים נגדיר לולאה שתרוץ מספר מסויים של פעמים (נניח 100) אבל בפועל נרצה שתרוץ פחות פעמים במידה ותנאי מסויים מתקיים. בפוסט הזה אראה שתי דרכים לבצע זאת.

דילוג באמצעות CONTINUE

לפעמים נרצה לדלג על חזרות מסויימות של הלולאה תוך כדי ריצה. אנחנו יכולים להגדיר את תנאי הדילוג בעזרת הפקודה CONTINUE. במקרה כזה אנחנו מגדירים תנאי לוגי (למשל אם X = Y) וכאשר הוא מתקיים הלולאה "תמשיך" הלאה, כלומר תדלג על מה שמופיע אחרי משפט ה-CONTINUE ותחזור חזרה לראש הלולאה לביצוע ריצה נוספת. הקוד שיופיע לפני משפט ה-CONTINUE יבוצע כרגיל והדילוג יתרחש רק לגבי הקוד שמופיע אחר כך. כדי להדגים את הפעולה, אשתמש בתוכנית מהפוסט הקודם. מטרת התוכנית הייתה לחשב כמה דמויות בטבלת הדמויות נאמנות לכל בית או קבוצה ולהדפיס הודעה מתאימה עבור כל בית. התוכנית נראית כך:

והתוצאה נראית כך:

loop_result

עכשיו, נניח שקבוצות שיש להן מתחת ל-4 תומכים נחשבות לזניחות ואני לא רוצה לכלול אותן ברשימה הסופית. אשתמש ב-CONTINUE כדי לדלג על ההדפסה של המשפט במידה ומספר העוקבים קטן מ-4:

אבל יש בעיה אחת – אם אציב את תנאי הדילוג לפני ההדפסה זה אומר שאדלג גם על ההקפצה של המשתנה counter מה שאומר ש-SQL Server ימשיך לבדוק כל הזמן את אותו מספר בית, ימשיך לקבל 0 במספר התומכים וימשיך לקפוץ לראש הלולאה – נתקעתי בלולאה אין סופית. לכן כשמשתמשים בתנאי דילוג חשוב לוודא שמקדם הלולאה נכתב מעל כדי שהלולאה אכן תמשיך להתקדם. אפתור את הבעיה על ידי הצבה של קידום המשתנה בתחילת הלולאה וכדי לתמוך בשינוי הזה אשנה את הערך ההתחלתי שלו ל-0:

עכשיו התוצאה הסופית נראית ככה:

loop_result2

שימו לב שאת תנאי הדילוג רשמתי מייד אחרי בדיקת מספר העוקבים. במידה ומספרם נמוך מ-4 אני מדלג על ההדפסה אבל גם אין לי צורך לבדוק אפילו מה שם הקבוצה הזאת ולכן אדלג גם על הבדיקה הזאת.

יציאה מלולאה באמצעות BREAK

לפעמים נרצה להגדיר שאם תנאי מסויים מתקיים אנחנו לא מסתפקים רק בדילוג על הריצה הנוכחית, ורוצים להפסיק את פעולתה של הלולאה לגמרי ללא קשר למספר הפעמים שעוד נשאר לה לרוץ (בהתאם לתנאי הכניסה). לשם כך נשתמש בפקודת BREAK שתופיע, בדומה ל-CONTINUE לאחר תנאי לוגי בגוף הלולאה. במקרה הזה נניח שאני מחליט שלא אכפת לי כמה בתים יש בטבלה, אבל אני רוצה שהבית האחרון שאני בודק יהיה Targaryen (אחריו אין לי צורך להמשיך לבדוק את שאר הבתים). כאן אני כבר זקוק לשתי הבדיקות כי אני מעוניין לצאת מהלולאה אחרי ביצוע התוכנית עבור הבית:

עכשיו התוצאה תראה ככה:

loop_result3

גם במקרה של CONTINUE וגם במקרה של BREAK התנאים אינם מחייבים. בדוגמה האחרונה, טבלת קבוצות שלא הייתה מכילה את בית Targaryen הייתה מקבלת סריקה מלאה והלולאה הייתה מסיימת את מספר הריצות שהוגדר לה. בדוגמה של CONTINUE היינו עשויים להראות את כל הבתים, אם כולם היו גדולים מספיק, או לא להראות אף שורה אם כל הבתים היו בעלי 3 עוקבים ומטה – הלולאה פשוט הייתה מדלגת על כל השורות בטבלה.