הבלוג של גרי רשף

07/04/2011

חסכו ואמצו (2)

Filed under: Uncategorized — תגיות: , , , — גרי רשף @ 20:57

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

למלא טבלה בנתונים – כל אחד יכול, למשל במספרי object_id של האובייקטים השונים במערכת:

If Object_ID('tempdb..#T13') Is Not Null Drop Table #T1;

Create Table #T1(Object_ID Int);


Insert

Into    #T1(Object_ID)

Select  Object_ID

From    sys.objects;

נניח שאני רוצה למלא שתי טבלאות בנתונים, כל זאת בפעולה – מבלי לבצע את הנ"ל פעמיים: ניתן לעשות זאת באמצעות האופרטור Output:

If Object_ID('tempdb..#T1') Is Not Null Drop Table #T1;

Create Table #T1(Object_ID Int);


If Object_ID('tempdb..#T2') Is Not Null Drop Table #T2;

Create Table #T2(Object_ID Int);


Insert

Into    #T2(Object_ID)

Select  Object_ID

From    (Insert

        Into    #T1(Object_ID)

        Output  Inserted.Object_ID

        Select  Object_ID

        From    sys.objects) T;

כלומר- האופרטור מציג את הרשומות שנקלטו ל-T1# בעזרת Output (ב-Subquery), והן נקלטות על ידי השאילתה החיצונית לתוך #T2.

האם ניתן לקלוט את הנתונים לטבלה שלישית באותה שיטה על ידי רמת קינון נוספת? למרבה הצער לא:

clip_image002

במקרה זה רווח והצלה יעמדו לנו ממקום אחר, למשל- נריץ את השאילתה שמעדכנת שתי טבלאות (בצירוף Output לשאילתה החיצונית) בעזרת Exec,

ואת הפלט של ה-Exec נקלוט לטבלה שלישית:

If Object_ID('tempdb..#T1') Is Not Null Drop Table #T1;

Create Table #T1(Object_ID Int);


If Object_ID('tempdb..#T2') Is Not Null Drop Table #T2;

Create Table #T2(Object_ID Int);


If Object_ID('tempdb..#T3') Is Not Null Drop Table #T3;

Create Table #T3(Object_ID Int);


Insert

Into    #T3

Exec('Insert

    Into    #T2(Object_ID)

    Output  Inserted.*

    Select  Object_ID

    From    (Insert

            Into    #T1(Object_ID)

            Output  Inserted.Object_ID

            Select  Object_ID

            From    sys.objects) T')

כאמור, יש רק פניה אחת לטבלה sys.objects, ושלוש פקודות Insert Into.

האם ניתן לקלוט את הנתונים לטבלה רביעית על ידי ביצוע Output לפעולת ה-Exec? לדאבוני לא:

clip_image004

כלומר- לא ניתן להשתמש ב-Output בהפעלה על ידי Exec, וממילא לא ניתן לקלוט זאת.

ניסיתי להיעזר ב-OpenRowset שהוא מכשיר השרצים של SQL Server ומאפשר לעשות הרבה דברים שאסור, אך משום מה התנהגותו תמוהה:

Use tempdb;

Go


If Object_ID('T1') Is Not Null Drop Table T1;

Create Table T1(Object_ID Int);


Select *

From OPENROWSET('SQLOLEDB','Server=.;Trusted_Connection=yes;',

    'Insert 

    Into    tempdb..T1(Object_ID)

    Output  Inserted.*

    Select  Object_ID

    From    sys.objects')


Select * From T1;

clip_image006

לכאורה הריצה מצליחה וה-Output מוצג כנדרש, אך הטבלה נותרת ריקה.

בהזדמנות אנסה לתרץ זאת.

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

If Object_ID('#T1') Is Not Null Drop Table #T1;


Select Object_ID

Into   #T1

From   sys.objects;

Go


Delete    #T1

Output    Deleted.Object_ID

Into      #T1(Object_ID);


Select * From #T1;

clip_image008

בשלב ראשון יצרנו טבלה עם נתונים,

ולאחר מכן מוחקים ממנה את הנתונים תוך הפנייתם חזרה אליה,

וכך כמו סיר הפסטה או פך השמן- מאליה היא מתמלאת.

לסיכום- הצלחנו למלא שלוש טבלאות במקביל בנתוני טבלה אחת, ומי שמצליח יותר- אשמח לשמוע כיצד.

מודעות פרסומת

להגיב »

עדיין אין תגובות.

RSS feed for comments on this post. TrackBack URI

להשאיר תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s

יצירה של אתר חינמי או בלוג ב־WordPress.com.

%d בלוגרים אהבו את זה: