מגבלות ה-Sequence ופריצתן

25/11/2010

אין תגובות

כמה ימים לאחר שפירסמתי את הפוסט שלי לגבי Sequence – מספור אוטומטי משותף, פרסם איציק בן-גן פוסט באותו נושא, ומה לעשות- חוץ מזה שהוא תותח מבחינה טכנית, הוא מבין את הפילוסופיה של ה-SQL לעומק – והבנה כזו לא פוגשים הרבה; ואני מתייחס כאן בעיקר לכך שהוא הראה ששליפה כפולה מ-Sequence בסגנון של

Select    Next Value For MySeq ID1,

        Next Value For MySeq ID2;

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

במילים אחרות- ה-Sequence אינו טבלה שכל Next שולף ממנה ערך נוסף, אלא אובייקט שיש לו ערך שוטף והוא זה שמוצג; או לחילופין- אם ניצור טבלה עם עמודת Identity בשם 1ID ועמודה מחושבת המציגה את ערכה של עמודת ה-Identity – שתיהן יציגו אותו ערך ולא תתבצע שליפה כפולה של ה-Identity.

יש להודות שיש בזה הגיון, אם כי לא הייתי נופל מהכיסא והאדמה לא הייתה רועדת אם זה לא היה כך.

בצד העובדה שה-Sequence חייב להיות אחיד בתוך הרשומה, הוא אינו יכול להיות אחיד בין הרשומות: לא ניתן לשכפל On The Fly את הערך השוטף בין מספר רשומות, למשל:

Select    *

From    sys.objects

Cross Join (Select Next Value For MySeq ID) T;

פקודה זו לא תחזיר אותו ערך לכל השורות מהטבלה אלא תיצור שגיאה:

Msg 11719, Level 15, State 1, Line 4

NEXT VALUE FOR function is not allowed in check constraints, default objects, computed columns, views, user-defined functions, user-defined aggregates, sub-queries, common table expressions, or derived tables.

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

נו טוב- תמיד ניתן למצוא איזו פירצה, למשל בעזרת OpenRowset..

קודם כל נקנפג את המערכת- מכיוון שהתקנו את השרת עם גרסת Denali CTP1 רק לאחרונה- ספק אם כבר עשינו זאת:

Exec sp_Configure 'show advanced options', 1;

Reconfigure;

Go

 

Exec sp_configure 'Ad Hoc Distributed Queries', 1;

Reconfigure;

Go

וכעת נשלוף שני ערכים עוקבים באותה שורה:

Select    *,

        Next Value For MySeq ID1

From    Openrowset ('Sqloledb','Server=localhost;Trusted_Connection=Yes','Set Fmtonly Off Select Next Value For MySeq ID2;') T;

ולחילופין- נשכפל אותו ערך מספר פעמים:

Select    *

From    Openrowset ('Sqloledb','Server=localhost;Trusted_Connection=Yes','Set Fmtonly Off Select Next Value For Reconfigure V1;') T

Cross Join sys.objects;

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

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