DCSIMG
February 2010 - Posts - גרי רשף

February 2010 - Posts

בכמה אופנים ניתן לחלק 3 מטבעות? 3 2,1 1,1,1 כלומר- 3 אפשרויות; כאשר ברור ש-2,1 ו-1,2 הן היינו הך. ובכמה אופנים ניתן לחלק N מטבעות (נוסחה כללית למקרה הפרטי הנ"ל)? לכאורה בעייה פשוטה מהסוג שפוגשים במבוא להסתברות, אלא שלמרבה הפלא אין לבעייה זו תשובה, ולהרחבה ניתן לעיין בוויקיפדיה. את הנוסחה הנכספת אינני מתיימר למצוא, אבל ננסה לטפל במקרים פרטיים- למשל חלוקה של 5 מטבעות. מה עדיף- פתרון מסובך ואיטי או פתרון אלגנטי ומהיר? דילמה קשה!.. נתחיל מהמסובך והאיטי שהיתרון העיקרי שלו שהוא יגרום לנו להעריך את האלגנטי והמהיר שבעתיים. ניצור את סדרת המספרים 0..5, נבצע 5 פעמים Join שלה עם עצמה, ונציג את כל הצירופים בהם סכום המספרים המתקבלים הוא 5. כדי למנוע כפילויות נקפיד שהסדרה תירד משמאל לימין (למשל 2,2,1,0,0 או 5,0,0,0,0 או 1,1,1,1,1), וכדי להקל על המערכת נקבע שהסדרה הראשונה תנוע בין 0 ל-5, השניה בין 0 ל-5/2, השלישית בין 0 ל-5/3 וכו' (מתחייב מהתנאי שהסדרה יורדת):
With Nm As
(Select 0 N
Union All
Select    N+1
From    Nm
Where    N<5)
Select    --Nm1.N+Nm2.N+Nm3.N+Nm4.N+Nm5.N Nm,
        *
From    Nm Nm1, Nm Nm2, Nm Nm3, Nm Nm4, Nm Nm5
Where    Nm1.N<=5/1 And Nm2.N<=5/2 And Nm3.N<=5/3 And Nm4.N<=5/4 And Nm5.N<=5/5
        And Nm1.N+Nm2.N+Nm3.N+Nm4.N+Nm5.N=5
        And Nm1.N>=Nm2.N And Nm2.N>=Nm3.N And Nm3.N>=Nm4.N And Nm4.N>=Nm5.N
Order By Nm1.N,Nm2.N,Nm3.N,Nm4.N,Nm5.N
נקבל 7 אפשרויות. מכיוון שלכל מספר לשאילתה יש מבנה שונה, ניצור את משפט ה-SQL באופן דינאמי ונריץ אותו:
Declare    @N Int,
        @SQL Varchar(Max),
        @SQLs Varchar(Max),
        @SQLf Varchar(Max),
        @SQLw0 Varchar(Max),
        @SQLw1 Varchar(Max),
        @SQLw2 Varchar(Max),
        @SQLo Varchar(Max);
Set        @N=5;
Set        @SQLs='';
Set        @SQLf='';
Set        @SQLw0='';
Set        @SQLw1='';
Set        @SQLw2='';
Set        @SQLo='';
With Nm As
(Select 0 N
Union All
Select    N+1
From    Nm
Where    N<@N)
Select    @SQLs=@SQLs+'Nm'+Cast(N As Varchar)+'.N+',
        @SQLf=@SQLf+'Nm Nm'+Cast(N As Varchar)+', ',
        @SQLw0=@SQLw0+'Nm'+Cast(N As Varchar)+'.N<='+Cast(@N As Varchar)+'/'+Cast(N As Varchar)+' And ',
        @SQLw1=@SQLw1+'Nm'+Cast(N As Varchar)+'.N+',
        @SQLw2=@SQLw2+Case When N=@N Then '' Else 'And Nm'+Cast(N As Varchar)+'.N>=Nm'+Cast(N+1 As Varchar)+'.N ' End,
        @SQLo=@SQLo+'Nm'+Cast(N As Varchar)+'.N,'
From    Nm
Where    N>=1;
Set        @SQL='With Nm As'+CHAR(13)+
            '(Select 0 N'+CHAR(13)+
            'Union All'+CHAR(13)+
            'Select    N+1'+CHAR(13)+
            'From    Nm'+CHAR(13)+
            'Where    N<'+Cast(@N As Varchar)+')'+CHAR(13)+
            'Select    --' + Left(@SQLs,Len(@SQLs)-1)+' Nm,'+CHAR(13)+
            '        *'+CHAR(13)+
            'From    '+Left(@SQLf,LEN(@SQLf)-1)+CHAR(13)+
            'Where    '+Left(@SQLw0,LEN(@SQLw0)-4)+CHAR(13)+
            '        And '+Left(@SQLw1,Len(@SQLw1)-1)+'='+CAST(@N As Varchar)+CHAR(13)+
            '        '+@SQLw2+CHAR(13)+
            'Order By '+Left(@SQLo,Len(@SQLo)-1);
Print    @SQL;
Exec(@SQL);
כפי שאפשר לראות- SQLs@ יוצר באופן דינאמי את ה-Select, SQLf@ את ה-From, SQLw123 את תנאי ה-Where (שלוש סדרות של תנאים), SQLo@ את ה-Order By, ו-SQL@ את המשפט כולו. ה-CTE המתחיל ב-With יוצר את המספרים 0..5, ובנוסף גם ב-SQL הדינאמי נוצר CTE דומה. בדוגמה זו N=5@, אך ניתן להציב איזה מספר שרוצים. ועכשיו לפתרון הפשוט: למספרים 1..5 נשרשר מספרים שאינם גדולים מהם כל עוד הסכום של כולם אינו גדול מ-5, כל זאת על ידי CTE רקורסיבי כפול (הראשון עבור המספרים 1..5 והשני עבור החלוקות השונות):
Declare    @N Int;
Set        @N=5;
With Nm As
(Select 1 N
Union All
Select    N+1
From    Nm
Where    N<@N),
Haluka As
(Select    CAST(N As Varchar(Max)) Haluka,
        N As Ahron,
        N As Total
From    Nm
Union All
Select    H.Haluka+','+CAST(Nm.N As Varchar(Max)),
        Nm.N,
        H.Total+Nm.N
From    Haluka H
Inner Join Nm
        On H.Ahron>=Nm.N
        And H.Total+Nm.N<=@N)
Select    Haluka
From    Haluka
Where    Total=@N;
גם בדוגמה זו N=5@, אך ניתן להציב איזה מספר שרוצים.
ספרת הביקורת בתעודת הזהות מחושבת כך: את הספרות במקומות האי-זוגיים החל מצד ימין כופלים ב-2 וסוכמים את הספרות (נניח אם מופיעה הספרה 8 – כופלים אותה ב-2 ומקבלים 16, וסכום הספרות הוא 7), את הספרות במקומות הזוגיים כופלים ב-1 (כלומר- לוקחים אותן כמו שהן), סוכמים את כל המכפלות, והמשלים למספר העגול הבא (שמתחלק ב-10) הוא ספרת הביקורת. נניח שתעודת הזהות היא 9148, אזי מימין לשמאל: 8*2=16 וסכום הספרות 7, 4*1=4, 1*2=2, 9*1=9. נסכום את המכפלות: 7+4+2+9=22, המשלים ל-30 הוא 8, ולכן 8 היא ספרת הביקורת. ספרת הביקורת נועדה לוודא שלא חלה טעות בהקלדת המספר: אם עשינו טעות כמו השמטת ספרה, הקלדה של אותה ספרה פעמיים, או הקלדה של ספרה לא נכונה – ספרת הביקורת לא תתאים וכך נעלה על הטעות. ברור שאם נעשה יותר מטעות אחת- יש סיכוי של 1:10 שהטעויות יקזזו זו את זו וספרת הביקורת תצא במקרה נכונה.. הפתרון לזה יכול להיות הקלדה כפולה של תעודת הזהות- בערך כמו שמקובל כשבוחרים סיסמה, אלא שהטרחה כאן גדולה – אם מקלידים מספר גדול של תעודות זהות, ועדיין יש סיכוי שנחזור פעמיים על אותה טעות. ספרת הביקורת נותנת אם כך הגנה סבירה נגד טעויות נפוצות. ולעצם העניין- לחישוב ספרת הביקורת ניתן לכתוב פונקציה מתאימה (UDF) אבל אני אעשה זאת באופן ישיר בשליפה עצמה. אינני יודע אם זה יותר יותר יעיל או פחות יעיל, אבל יש לזה יתרון צנוע: לא צריך לרוץ אחר ה-DBA, למלא טופס בקשה בשלושה עותקים, ולהתחנן שיואיל בטובו להכניס לדטבייס את הפונקציה (שלא לדבר על תיקונים בעתיד).. ניצור קודם כל טבלת נתונים:
Create Table T_Employees(TZ Varchar(10) Not Null Primary Key,Name Varchar(20));
Go
Insert Into T_Employees Values('330123123','Avi');
Insert Into T_Employees Values('5659824','Batya');
Insert Into T_Employees Values('65936224','Galit');
Insert Into T_Employees Values('45205957','Dan');
Insert Into T_Employees Values('571425','Hila');
Go
בגרסת 2008 ניתן לבצע את כל פעולות ה-Insert בפעם אחת, אך מתוך התחשבות במשתמשי 2005 שאין ידם משגת- נכניס כל רשומה בנפרד.. וכעת לשליפה:
Select    TZ,
        Right(10-Right(Cast(Right(SUBSTRING(Reverse(TZ),1,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),1,1) As TinyInt)>=5 Then 1 Else 0 End+
            Cast(SUBSTRING(Reverse(TZ),2,1) As TinyInt)+
            Cast(Right(SUBSTRING(Reverse(TZ),3,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),3,1) As TinyInt)>=5 Then 1 Else 0 End+
            Cast(SUBSTRING(Reverse(TZ),4,1) As TinyInt)+
            Cast(Right(SUBSTRING(Reverse(TZ),5,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),5,1) As TinyInt)>=5 Then 1 Else 0 End+
            Cast(SUBSTRING(Reverse(TZ),6,1) As TinyInt)+
            Cast(Right(SUBSTRING(Reverse(TZ),7,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),7,1) As TinyInt)>=5 Then 1 Else 0 End+
            Cast(SUBSTRING(Reverse(TZ),8,1) As TinyInt)+
            Cast(Right(SUBSTRING(Reverse(TZ),9,1)*2,1) As TinyInt)+Case When Cast(SUBSTRING(Reverse(TZ),9,1) As TinyInt)>=5 Then 1 Else 0 End+
            Cast(SUBSTRING(Reverse(TZ),10,1) As TinyInt),1),1) SB,
        Name
From    T_Employees;
כפי שאפשר לשים לב אני הופך את המחרוזת בעזרת הפונקציה Reverse וכך ניתן למנות את המקומות משמאל כמקובל, ובכל שורה מטפל בספרה אחרת כאשר המקומות הריקים נחשבים ל-0. השליפה נראית לא יעילה: ה-Reverse מחושב 15 פעמים לכל תעודת זהות, וחלק מהספרות נשלפות פעמיים בעזרת Substring; אבל גם כשמנעתי זאת על ידי קינון שאילתות – היעילות מבחינת ה-Execution Plan לא השתנתה. ליתר בטחון וכדי שלא יהיו לי נקיפות מצפון, הנה השליפה המקוננת:
Select    TZ,
        Right(10-Right(Cast(Right(TZ1*2,1) As TinyInt)+Case When TZ1>=5 Then 1 Else 0 End+
            TZ2+
            Cast(Right(TZ3*2,1) As TinyInt)+Case When TZ3>=5 Then 1 Else 0 End+
            TZ4+
            Cast(Right(TZ5*2,1) As TinyInt)+Case When TZ5>=5 Then 1 Else 0 End+
            TZ6+
            Cast(Right(TZ7*2,1) As TinyInt)+Case When TZ7>=5 Then 1 Else 0 End+
            TZ8+
            Cast(Right(TZ9*2,1) As TinyInt)+Case When TZ9>=5 Then 1 Else 0 End+
            TZ0,1),1) SB,
        Name
From    (Select    *,
                Cast(SUBSTRING(ZT,1,1) As TinyInt) TZ1,
                Cast(SUBSTRING(ZT,2,1) As TinyInt) TZ2,
                Cast(SUBSTRING(ZT,3,1) As TinyInt) TZ3,
                Cast(SUBSTRING(ZT,4,1) As TinyInt) TZ4,
                Cast(SUBSTRING(ZT,5,1) As TinyInt) TZ5,
                Cast(SUBSTRING(ZT,6,1) As TinyInt) TZ6,
                Cast(SUBSTRING(ZT,7,1) As TinyInt) TZ7,
                Cast(SUBSTRING(ZT,8,1) As TinyInt) TZ8,
                Cast(SUBSTRING(ZT,9,1) As TinyInt) TZ9,
                Cast(SUBSTRING(ZT,10,1) As TinyInt) TZ0
        From    (Select    *,
                        REVERSE(TZ) ZT
                From    T_Employees) T) T;
Posted by גרי רשף | with no comments

כנראה שנגמרו הבעיות אם יש לנו זמן לשחק ב-"בול פגיעה".
החוקים למי שבמקרה אינו מכיר: שחקן א' בוחר מספר בן 4 ספרות שונות (למשל 1528), ושחקן ב' מנסה לנחש.
התשובה על כל ניחוש של ב' צריכה להיות מספר ה"בולים" (כלומר- כמה ספרות מתוך ה-4 שבניחוש נמצאות במקום הנכון),
ומספר ה"פגיעות" (כלומר- כמה ספרות מתוך ה-4 מופיעות במספר שבחר א' אך לא במקום הנכון).
למשל אם א' בחר 0123 ו-ב' מנחש שהמספר הוא 1283, אזי יש לו "בול" אחד (הספרה 3) ושתי "פגיעות" (הספרות 1 ו-2).
כעת ב' מציע ניחוש חדש על סמך המידע החלקי שבידו, וחוזר חלילה עד שהוא מנחש נכונה את המספר.

אנחנו נבחר מספר והמחשב ינחש ויגלה,
ולשם כך נכתוב פרוצדורה שתיצור טבלה עם 10*9*8*7=5040 הצירופים החוקיים,
בטבלה יהיה שדה שיציין אם המספר אפשרי לאור המידע שקיבלנו עד כה (בהתחלה לכל המספרים אינדיקציה 1 ובכל איטרציה המחשב יאפס אותה עבור הלא רלוונטיים),
והמחשב יבחר רשומה אחת באופן אקראי ויציג אותה כניחוש:

Create Proc SP_BulPgia_Begin As






If (Select Count(*) From sys.tables Where name='T_BulPgia')=1 Drop Table T_BulPgia;



Create Table T_BulPgia(A Char(1),B Char(1),C Char(1),D Char(1),YesNo Bit);



Create Unique Clustered Index T_BulPgia_Idx On T_BulPgia(A,B,C,D);






With Nm As



(Select 0 N



Union All



Select    N+1



From    Nm



Where    N<9)



Insert Into T_BulPgia



Select    Cast(N1.N As Char) A,



        Cast(N2.N As Char) B,



        Cast(N3.N As Char) C,



        Cast(N4.N As Char) D,



        1 YesNo



From    Nm N1



Inner Join Nm N2



        On N2.N<>N1.N



Inner Join Nm N3



        On N3.N<>N1.N



        And N3.N<>N2.N



Inner Join Nm N4



        On N4.N<>N1.N



        And N4.N<>N2.N



        And N4.N<>N3.N;






Select    Top 1 'My guess: '+A+B+C+D



From    T_BulPgia



Order By NewID();

כעת נכתוב פרוצדורה נוספת שתקבל את הניחוש האחרון של המחשב, את מספר הבולים ואת מספר הפגיעות (שלושה פרמטרים בסה"כ),

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

ומתוך הרשומות שהאינדיקציה שלהן היא עדיין 1 המחשב ישלוף אקראית ניחוש נוסף.

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

Create Proc SP_BulPgia_Guess(@Guess Char(4), @Bul Int, @Pgia Int) As






With T As



(Select    *,



        Case When SUBSTRING(@Guess,1,1)=A Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,2,1)=B Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,3,1)=C Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,4,1)=D Then 1 Else 0 End Bul,



        Case When SUBSTRING(@Guess,2,3) Like '%'+A+'%' Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,1,1)+SUBSTRING(@Guess,3,2) Like '%'+B+'%' Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,1,2)+SUBSTRING(@Guess,4,1) Like '%'+C+'%' Then 1 Else 0 End +



        Case When SUBSTRING(@Guess,1,3) Like '%'+D+'%' Then 1 Else 0 End Pgia



From    T_BulPgia



Where    YesNo=1)



Update    T



Set        YesNo=0



Where    Not (Bul=@Bul And Pgia=@Pgia);






Select    Top 1 Case (Select COUNT(*) From T_BulPgia Where YesNo=1) When 1 Then 'The answer is: ' Else 'My guess: ' End +A+B+C+D



From    T_BulPgia



Where    YesNo=1



Order By NewID();

נתחיל לשחק: בחרתי את המספר 1528 (לא לגלות למחשב- הוא צריך למצוא לבד!) והפעלתי את הפרוצדורה SP_BulPgia_Begin.

הניחוש שלו 6342 שזה 0 בולים ו-1 פגיעות ולכן אני מפעיל את הפרוצדורה SP_BulPgia_Guess עם הפרמטרים '6342',0,1.

הניחוש שלו עכשיו 2015 שזה 0 בולים ו-3 פגיעות,

הניחוש הבא שלו 7201 שזה 0 בולים ו-2 פגיעות,

הניחוש הבא שלו 1530 שזה 2 בולים ו-0 פגיעות,

הניחוש הבא (שבמקרה הוא גם התשובה הנכונה) הוא 1528 וזה 4 בולים ו-0 פגיעות,

ורק כעת הוא מכריז ש-1528 זו התשובה הנכונה:

SP_BulPgia_Begin;            --My guess: 6342



SP_BulPgia_Guess '6342',0,1;--My guess: 2015



SP_BulPgia_Guess '2015',0,3;--My guess: 7201



SP_BulPgia_Guess '7201',0,2;--My guess: 1530



SP_BulPgia_Guess '1530',2,0;--My guess: 1528



SP_BulPgia_Guess '1528',4,0;--The answer is: 1528

AZURE מבוא והתחברות SQL Azure שהוא גרסת SQL Server in the Cloud יצאה בגרסת CTP להתנסות חופשית במהלך 2009, והופכת במהלך 2010 לשירות בתשלום. לא הכל ידוע עליה כרגע, ולכן מה שנכתב כאן הוא בערבון מוגבל- מציג את הידוע לי, ואת התרשמותי הסובייקטיבית. יתכנו טעויות או אי דיוקים, וממילא דברים ישתנו בקרוב; ולכן כל מה שנכתב כאן נכון לתאריך הכתיבה. Cloud Computing מתייחס ליישומים ממוחשבים שנמכרים כשירות ללקוח, כך שהשרתים אינם ברשותו והוא משלם תמורת השירות בו הוא משתמש. מקור המונח Cloud הוא בתרשימים ארגוניים בהם רכיבים שהם מחוץ לתחום (Scope) מוצגים כצורה גיאומטרית לא מוגדרת שנראית כענן; ומיקרוסופט נתנה לשירותי ה-Cloud שהיא מספקת את השם Azure – מילה באנגלית ספרותית שמקורה פרסי, ואשר מציינת כחול-שמיים.. SQL Azure הוא סוג של שירות Hosting המציין לא רק את השירות שמיקרוסופט מוכרת, אלא גם גרסה מיוחדת של SQL Server המבוססת על גרסת 2008; כשכרגע יש שתי חוות שרתים בארה"ב, ובעתיד יתווספו עוד כמה באירופה ובמזרח אסיה. ההגדרות הראשוניות נעשות באתר http://SQL.Azure.com (יש להתחבר בעזרת קוד שמקבלים ממיקרוסופט ו-Windows Live ID), שם מגדירים בקלות שרת, דטבייסים (את זה לא חייבים לבצע משם), והרשאות IP: קיימת שכבת הגנה ברמת ה-IP, בהנחה שהכתובות ידועות וקבועות. כרגע הדטבייסים מוגבלים בגודלם ל-10GB – כנראה כדי להבטיח דטבייסים קטנים + עומסים קטנים + בעיות קטנות בשלב זה. כמובן שזה מעורר תהיות לגבי ההבטחות ל-Scalabillity ולכך שהלקוח יוכל לצרוך משאבים על פי הצורך מבלי לערוך תחזיות ולהיערך מראש.. להקלת הגלולה המרה כדאי לציין שבהיעדר Log ו-tempdb – אין מגבלות על השימוש במשאבים אלו. ניתן להתחבר לדטבייס מה-SSMS בתנאי שהתקנו גרסת 2008 R2, ואם לא- ניתן להיעזר בתחליף SSMS כמו זה: http://MicroGuru.com/Gem. ההתחברות מה-SSMS די דומה להתחברות SQL Server Authentication עם שם משתמש וסיסמה, אך בנוסף יש לציין את שם הדטבייס ב-Options (וכמובן- לתת הרשאה ל-IP שלנו). אפשרות אחרת היא להתחבר בעזרת SQLCmd כך (יש להיכנס למסך Cmd להרצת CommandLine ולשנות את מה שמופיע בכחול לערכים האמיתיים):

SQLCMD -U MyUserName@MyServer -P MyPwd -S tcp:MyServer.database.windows.net -d MyDB

לאחר מכן נקבל שורות ממוספרות במקום את הקידומת הרגילה, שם נכתוב פקודות SQL, וכדי להריץ אותן- נכתוב Go; ולסיום העבודה עם SQLCmd – נכתוב Exit. כדאי לציין שללא התקנת Client של SQL Server – לא ניתן להשתמש ב-SSMS או ב-SQLCmd, ומכאן שכרגע השירות שימושי רק למי שכבר יש לו SQL Server "רגיל" (On Premise).. בכל מקרה- כעת העבודה איטית בכל מה שקשור להעברת נתונים מהשרת למשתמש ולהיפך, וה-Connection מתנתק מאוד מהר, מחייב התחברות מחודשת בכל פעם, ולא מאפשר להריץ פקודות שזמן עיבודם רב (בנוסף- ל-SQL Azure אין כרגע Agent ולכן לא ניתן להריץ פקודות אסינכרוניות כך שיתבצעו בשרת ללא קשר למשתמש הקצה). מה פועל וכיצד ומה לא על ידי הרצת הפקודה Select @@Version נוכל לראות שמדובר בגרסת SQL Server מיוחדת, ומהעובדה שפונקציות שקיימות רק מגרסת 2008 פועלות בה ניתן ללמוד שהיא מבוססת על SQL 2008. מדובר בפונקציות כמו פונקציות השעה והתאריך החדשות, היכולת להכניס מספר רשומות בבת אחת על ידי (..), (..) Insert Into .. Values , ו-Compound Assignment (למשל Set @I+=5 להוספת 5 למשתנה). לטבלאות הנוצרות במערכת חייב להיות Clustered Index (הסיבה לכך היא שברקע פועלת מערכת רפליקציות שנועדה לגבות את הנתונים והיא מחייבת קיום Clustered Index על הטבלאות). שעת המערכת המתקבלת על ידי ()GetDate היא GMT, כלומר שעון גריניץ' (שעתיים אחרי ישראל בחורף ושלוש שעות בקיץ). מה פועל (בדיקה אקראית של אופציות שונות):
  • Create Database פועל אך ללא אופציה מלבד שם הדטבייס. למשל- לא ניתן לשנות את ה-Collation, והגדרת ה-Recovery Model אינה רלוונטית. בנוסף אין פקודת Alter Database.
  • BCP פועל, אך לא ניתן לייבא בעזרתו נתונים מכיוון שאת שם הדטבייס יש לציין יחד עם שם הטבלה (MyDB.dbo.MyTbl) ואופציה זו אינה נתמכת על ידי SQL Azure. בנוסף לא ניתן כנראה לשנות את ה-Default_Database של ה-Login..
  • SQLCmd פועל, כפי שהודגם.
  • Merge הפקודה המשלבת Insert + Update פועלת.
  • Pivot הפקודה היוצרת טבלאות דו-מימדיות פועלת.
  • UDF ניתן ליצור פונקציות משתמש.
  • User Defined Datatype
  • טריגרים: גם DML על נתונים בטבלה וגם DDL על אובייקטים בדטבייס, אך זה האחרון ללא פונקציית Eventdata שמאפשרת ללכוד את הפקודה, סוג השינוי, שם האובייקט וכו'; ובלעדיה טריגר DDL מאבד חלק גדול מאוד מכוחו.
  • Set StatisticsIO, Set Statistics Time (פונקציות שימושיות למדידת ביצועים).
  • Execution Plan.
  • DBCC Sgow_Statistics (כל שאר פונקציות DBCC אינן פועלות).
  • טבלאות זמניות, אך רק #מקומיות (לא ##גלובליות).
  • SSIS ,Excel, SSRS כשהם מופעלים מ-SQL Server רגיל (SQL Azure אינו תומך בכלי BI).
  • Collation – נתמך אך רק ברמת השדה. לא ניתן לשנות את זה של הדטבייס.
מה אינו פועל:
  • File System – אין אפשרות לגשת לדיסקים, לטפל ב-FileGroup ובקבצים וכו'.
  • Partitions – די מתבקש לאור העובדה ש"הפואנטה" בכלי זה היא היכולת לפצל טבלה לקבצים שונים.
  • FileStream, xp_CmdShell, BulkCopy – כלים ופונקציות הפונים ל-File System.
  • Agent + Jobs: לא ניתן לתזמן פעולות או לבצע הרצות א-סינכרוניות.
  • BI: ניתן לפנות ל-SQL Azure מסביבת BI חיצונית לו, אך לא עצמו אין BI.
  • SSAS (חיצוני): לא הצלחתי ליצור Data Source Views מכיוון שלא ניתן היה לקרוא את שמות הטבלאות שב-SQL Azure.
  • PowerPivot (תוסף חדש ל-Excel המאפשר טיפול במיליוני רשומות ויצירת BI אישי): לכאורה יש לו תמיכה מובנית ב-SQL Azure, אך קריאת הנתונים מטבלה בת כחצי מיליון רשומות איטית מאוד, ונפלה באמצע.
  • Mails: לא ניתן לקנפג למשלוח מיילים.
  • Compression – מגבלת ה-10GB אינה ניתנת לעקיפה באמצעות כלי זה..
  • Encryption
  • Linked Server, OpenRowSet וכו': לא ניתן להגדיר ב-SQL Azure וגם לא ניתן לפנות אליו בעזרתם.
  • DMV, Profiler, Traces, Activity Monitor, PerfMon וכו': יש ליצור לבד תשתית לכך אם רוצים.
  • רפליקציות. יש ב-SSMS "הכנה ל-" אך האופציה אינה פעילה.
  • גיבויים ושיחזורים. כשיהיו- כדאי שתהיה אופציה של גיבוי בשרת ה-Cloud מכיוון שהעברה של עשרות GB מה-Cloud ללקוח תימשך זמן רב מאוד.
  • Sp_Monitor, Sp_HelpDB, Sp_Who, Sp_HelpServer, Sp_Lock, Sp_SpaceUsed – פונקציות עזר ל-DBA לקבלת מידע על המערכת.
  • תוכנות צד שלישי (כמו Idera שניסיתי את הגרסה החופשית שלה).
  • פונקציות מבוססות Dot.Net כמו HierarchieId או GeoSpatial, וכן פונקציות Clr שנכתבות על ידי המשתמש.
  • Truncate Table.
שימושיות וחזון לעתיד לאור מגבלותיו של הכלי כיום- לא הייתי מנסה להשתמש בו לצרכים מסחריים, והייתי ממתין שהטכנולוגיה תבשיל ושיתווספו אופציות נוספות. המחיר כיום – כ-10$ ל-1GB לחודש או 100$ ל-10GB לחודש הוא זול יחסית לרמת המחירים של שירותי ה-Hosting, ובוודאי ביחס לעלות של אחזקת שרת ו-DBA-ים, ולכן – כשהכלי יהיה שימושי – זו בהחלט אופציה אטרקטיבית. שימושים אפשריים יכולים להיות:
  • הקמת מערכות מידע שתוחלת חייהן קצרה, למשל- מערכת תמיכה ליום בחירות או לכנס מקצועי או לאירוע חריג.
  • בסיסי נתונים לאתרי אינטרנט שכיום מוחזקים לא פעם בידי ספק השירות.
  • כל שימוש שמצדיק כיום פניה לשירותי Hosting.
ההערכה הרווחת שהשימוש ב-Cloud ילך ויגדל ככל שהשירות ישתפר, אם כי ברור שמערכות רבות ימשיכו לשבת על שרתים "רגילים" מטעמי בטיחות. נושא אבטחת המידע שנוי במחלוקת- מצד אחד המידע ישמר בידי מיקרוסופט, עלול לדלוף בדרך זו או אחרת, להיות מטרה להתקפות של האקרים ואלי אף ליפול לידיהם של גורמים מתוך מיקרוסופט. מצד שני- גם המידע המצוי כיום בידי רוב האירגונים – לא תמיד מוגן כהלכה, ויתכן שב-Cloud הוא יהיה הרבה יותר מוגן ממה שהוא כיום. יכולת השרידות של SQL azure אמורה להיות טובה מאוד, בעיקר לאור העובדה שחוות השרתים יפוזרו ברחבי העולם ושכל המערכת מוקמת באופן מאובטח, ולמעשה זה היתרון היחסי הגדול של השירות הזה. לא יהיה צורך בתחזוקה כמו במערכות מקומיות, לא בטכנאים או אנשי סיסטם או DBA-ים; וארגונים לא יצטרכו להחזיק מערכת תמיכה מקצועית שאינה בתחום ההתמחות שלהם. עד כה לא היו שידרוגים, ואינני יודע מה יקרה בעתיד- האם תובטח תאימות לאחור, או האם השירות יכלול גרסאות שונות וכל אחד יוכל לבחור עם איזו לעבוד. התנסות מעשית מעבר למה שמיקרוסופט מאפשרת- ניתן בינתיים להתנסות עם דטבייס שהקמתי בשרת שלי (אינני יודע עד מתי הוא יהיה פעיל):

Server: h6okwyeo51.database.windows.net

User: ISUG (ISUG@h6okwyeo51)

Password: SqlAzure2010

Database: ISUG

למשל, ניתן להתחבר בעזרת SQLCmd כך:

SQLCMD -U ISUG@h6okwyeo51 -P SqlAzure2010 -S tcp:h6okwyeo51.database.windows.net -d ISUG

עדכונים: 1. ב-17/02/2009 בוצע עדכון (Service Update 1) שמאפשר מספר פונקציות DMV. 2. ב-28/06/2010 ניתן יהיה להגדיל את הדטבייסים עד 50GB במקום 10GB עד כה.