content top
פקודות ה- SET חדשות

פקודות ה- SET חדשות

 

לאחר שבאחד הפוסטים ראיתי שמיקרוסופט תיקנה משהו ב ReportServer בעברית בזכות הערה של משתמש עברי (ככה אומרים, לא?), קפץ לי רעיון לפרסם פוסט לא על משהו שיש אלא על משהו שאין. מי יודע אולי זה יכנס ב 2012. ואם יהיו גם תומכים לזה – אולי אפילו עוד קודם.

האמת שבשלב מסוים כבר חשבתי לוותר בגלל הפדיחה של לכתוב משהו ש"חבל שלא קיים" ובסוף מסתבר שכבר ב SQLserver6.5 זה היה קיים ורק אני פספסתי את זה. בסוף החלטתי בכל זאת – הרי "אין הביישן למד" ואולי זה יפתח פתח לעוד כמה רעיונות נחמדים.

כידוע, בשבוע שעבר קראנו בפרשת "לֶךְ לְךָ", שזה בערך “GO TO”, אז לקחתי נושא של כתיבת סקריפטים שיש להם מספר אצוות (Batches) מופרדים ב"לך" (GO) בינהם. יש להם תכונות מאד מסוימות שלעיתים מעצבנות. כתבה ראשונה בסדרה…

אז הנה –רשימה חלקית לפניכם ואתם תשפטו:

1. כידוע, GO זה לא חלק מהשפה הסטנדרטית. זה פקודה ברמת ה CLIENT, שנותנת לשרת הוראת ביצוע. ה GO משחרר משתנים. ז"א אם הגדרנו משתנה מקומי, אחרי GO לא נוכל להשתמש בערך שלו, וזה בסדר. אפילו הגיוני – כמו סוף מודול. אם כך אז למה הוא לא משחרר טרנזקציות וטבלאות זמניות? סביר להניח שיש סיבה הגיונית לזה – אולי מפני שטרנזקציות וטבלאות זמניות אלו ישויות שמוגדרות ברמת השרת עבור Server Process (בשונה ממשתנים שנמצאים ב Client), והתהליך עצמו לא משתחרר (Disconnect) עם ביצוע ה GO. או קיי, ככה הוחלט ברדמונד ולמען האמת התרגלנו כבר. אבל למה לעזאזל אם יש שגיאה בזמן ריצה רק ה Batch מפסיק עד ה GO הקרוב? למה אי אפשר להגדיר ברמת ה CLIENT שתעופה מכל סוג שהוא (או מסוג מסוים) תעיף את הסקריפט לחלוטין? גם GOTO לא יעזור – הטווח שלו זה גם רק עד ל GO הקרוב, אז איך לעזאזל מפסיקים לחלוטין סקריפט שמכיל כמה אצוות בתוכו?

לדעתי היה יכול להיות לזה פתרון פשוט: SET חדש, בדומה ל xact_abort, אולי נקרא לו xript_Abort שאם הוא ON אז ה Script יעצור מיידית במקרה של שגיאה. וגם שישחרר טבלאות זמניות ויעשה ROLLBACK לטרנזקציות. אם כבר אז כבר.

האמת- לא מדויק שאי אפשר. בעזרת SQLCMD קיימת אפשרות להוסיף בתחילת הסקריפט את השורה:

:ON Error EXIT

וזה תופס לאורך כל הדרך. ברגע שתהיה תעופה – כל הסקריפט עף. אבל גם בזה יש מלכוד: את הסקריפט לא אני מריץ, אלא אנשי מחלקה אחרת שלא ממש שוחים בתחום, ולך תסביר להם איך להעביר את ה SSMS למצב של SQLCMD.

SET קטן – וגם זה לא היה בעיה.

2. נניח מוסיפים עמודה לטבלה ועושים לה UPDATE משפט אחד אחרי. זה לא שגיאת סינטקס, וגם לא ממש שגיאת ריצה (אם נריץ כל אחד בנפרד זה ידפוק כמו שעון). אבל אם נריץ ביחד ה SQL יודיע שחסר לטבלה עמודה – ז"א מיני סינטקס אחרי תחילת הריצה. קצת מטריד שבזמן שדרוג מערכת, אם רוצים לעשות UPDATE אחרי תוספת עמודה אפשר רק ב DYNAMIC SQL. או להפריד ב GO באמצע, אבל אז נעלמים המשתנים, וגם TRY-CATCH יורד מהפרק וכו'. כאן הפתרון פשוט יותר –שהקומפיילר יזהה את המצב ויאפשר סוג כזה של UPDATE . ולמי שמעונין לשמור על קומפטביליות אפשר להוסיף איזה SET קטן שיאפשר את זה…

אגב, בנסיון מקרי ראיתי שאם מוסיפים את העמודה ואח"כ מורידים שוב – שגיאת המיני-סינטקס נעלמת. יש הסבר לתופעה משוה זו? קשור אולי ל Versioning?

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

3. מסתבר ש TRY-CATCH תופס את רב סוגי השגיאות. סוג השגיאות שהוזכר בסעיף הקודם למשל הוא לא תופס וה BATCH נופל ל-GO הקרוב כמובן. אז זהו. גם אם הבנו שאי אפשר להפסיק סקריפט באמצע BATCH ורצינו לפתור בעזרת TRY-CATCH – גם אז הענין לא סגור. אם היו שואלים אותי – הייתי מכניס את כל סוגי השגיאות (למעט כאלה עם SEVERITY נמוך שהן אינן שגיאות) ל TRY-CATCH, אבל כמו שניחשתם-לא שאלו. באותו עניין, אם רוצים להציג את השגיאה ב CATCH, יש פונקציות מערכת כמו ERROR_MESSAGE() שמחזירות את נתוני השגיאה, אבל לעיתים השגיאה מורכבת משתי הודעות: למשל אם ננסה להוסיף מפתח זר לעמודה שלא קיימת, נקבל שתי הודעות שגיאה:

clip image002 thumb פקודות ה  SET חדשות

במקרה כזה השגיאה שתוצג זה רק השגיאה הסתמית השניה, בעוד שהראשונה האינפורמטיבית נעלמת.

 

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

קחו אובייקט, למשל טבלה או View, תעשו עליו SELECT (דאבל קליק) ואח"כ Alt-F1 – וראו זה פלא – כל נתוני האובייקט ייפרשו בחלון התוצאות. זה נוח במיוחד אם רוצים להעתיק נתון מנתוני הטבלה כמו שדות הטבלה, או אינדקס או מפתח זר, אז במקום לחפש את הטבלה ב Object Explorer ולגרור את השדות לעורך – הרי הם לפניכם. כמובן זה למי שלא מסתדר עם SQL Intellisense/SQL Prompt ודומיהם (כמוני).

ההסבר הוא פשוט – כברירת מחדל מוגדר לנו קיצור מקלדת (Keyboard shortcut) שמבצע SP_help על האובייקט ונותן את התוצאות מייד. זה כבר מוגדר אוטומטית בכל התקנת Client. אפשר למצוא הגדרות נוספות ב Tools – Options – Environment – Keyboard.

אני לקחתי את זה צעד אחד קדימה והגדרתי תחת Ctrl-F1 את הפקודה sp_helptext. ושוב – SELECT על שם הפרוצדורה או הפונקציה או הטריגר וכדו' + לחיצה על Ctrl-F1 ונקבל את הקוד בחלון ה Results ללא צורך לחפש בסייר משמאל. את זה אני לא בטוח שהאינטליסנס יודע לעשות.

Bookmark and Share

תגובה אחת ל “פקודות ה- SET חדשות”

  1. מאת סטאס:

    אורי, יש אפשרות לעצירה מוחלטת של ה-script.
    אני זוכר אותה מימי SQL 2000 כאשר Northwind ו-pubs היו חלק מכל התקנת SQL.
    ברוב ההתקנות אף אחד לא טרח למחוק אותם, אבל לי יצא להיתקל בשרת פיתוח ללא מסדי נתונים לדוגמא, אז הלכתי והורדתי scripts ליצירה של שניהם.
    בזמן יצירה של pubs קרתה תקלה, לא זוכר למה. להפתעתי אובייקטים לא נוצרו בתוך ה-master, אלא script עצר.
    הנה חלק מאותו קוד שיכול לעזור לך:

    if db_name() 'pubs'
    raiserror('Error in InstPubs.SQL, "USE pubs" failed! Killing the SPID now.'
    ,22,127) with log

השאר תגובה