SQL Server למפתחים: Transaction Isolation Level

הקדמה

SQL Server, כמו כל דטאבייס רלציוני טוב, עונה על סט של עקרונות שנקראים ACID: ר”ת של Atomicity, Consistency, Isolation, Durability שמטרתם להבטיח את שלמות הנתונים במסד הנתונים. ממש ממש בגדול – העקרונות הללו אומרים שכשאתם מכניסים מידע לדטאבייס הוא נשאר שם, כשאתם שולפים נתונים אתם מקבלים נתונים אמיתיים ונכונים [בלי להיכנס להגדרה של “אמיתיים ונכונים” עכשיו]. בפוסט הזה אני רוצה להתמקד רק באחת מהמילים הללו: Isolation. מדובר למעשה בהגדרה (לכאורה) פשוטה: ההבטחה שגם אם שתי טרנזקציות רצות במקביל, תוצאת הביצוע שלהן בפועל תהיה כאילו הן רצו אחת אחרי השנייה.
כמובן, שבפועל אנחנו כן נרצה שדברים יעבדו במקביל. ולכן, נרצה להגדיר באמת מה מובטח במקרה ששתי טרנזקציות רצות במקביל ומתעסקות מול אותם הנתונים, ומה לא מובטח.

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

SQL Server למפתחים: Indexed Views לטיפול בנתונים סיכומיים

הקדמה

Indexed view הוא פיצ’ר מאד שימושי, אבל גם באופן יחסי פחות מוכר – לפחות לאוכלוסיית המפתחים. מדובר למעשה בשילוב בין Views לבין אינדקסים “רגילים” (non-clustered indexes) שקיימים על טבלאות. לפני שנבין מה הבעייה, ואיך אפשר להשתמש ב- Indexed Views כדי לפתור אותה, ניישר קו לגבי מס’ מונחים.

View – אפשר לחשוב על view בתור שאילתת SELECT ששמורה בתור אובייקט ב-DB שלנו. אם, למשל, יש לנו view בשם MyView הוא יכול לייצג שאילתה כלשהי (למשל, SELECT ColumnA, Column B FROM MyTable WHERE ColymnC=5) וכל שאילתה שנריץ על ה- view תהיה בפועל כאילו הרצנו אותה על ה- result set שחוזר מהשאילתה של ה- VIEW. למשל, אם בדוגמא הזאת נריץ SELECT * FROM MyView WHERE ColumnA=1 אז אנחנו למעשה מתשאלים את כל השורות מטבלת MyTable שבהם ColumnC הוא 5 (מהגדרת ה- view) ו- ColumnA הוא 1 (מהשאילתה שאנחנו עושים).… להמשך קריאה

SQL Server למפתחים: Bulk Insert ו- SqlBulkCopy

הקדמה

כל מפתח שעובד/עבד מול דטאבייס באשר הוא יודע איך מכניסים שורות לטבלה. מדובר באחת מהפעולות הבסיסיות, INSERT,. למשל, אם יש לי טבלה שמכילה 3 עמודות: עמודת ID עולה (IDE

CREATE TABLE [dbo].[BulkInsertDemo](

    [ID] [int] IDENTITY(1,1) NOT NULL,

    [NumCol] [int] NOT NULL,

    [LongTextCol] [varchar](2000) NOT NULL,

 CONSTRAINT [PK_BulkInsertDemo] PRIMARY KEY CLUSTERED 

(

    [ID] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

NTITY), עמודה שמכילה ערך מספרי ועמודה של טקסט:

אזי ה- SQL Statement שבו נשתמש כדי להכניס שורות לטבלה הזאת הוא:

INSERT INTO BulkInsertDemo(NumCol, LongTextCol) VALUES (1, 'BlahBlahBlah')

שום דבר מתוחכם עד עכשיו.… להמשך קריאה

ייצור אוטומטי של סקריפטי התקנה והסרה של SQL CLR Functions / Stored Procedures

לפני כמה ימים פרסמתי פוסט על משהו קטן שעבדתי עליו בין תרגיל אינפי לתרגיל לינארית, שכולל למעשה אוסף של functions ו- stored procedures המאפשרים עבודה מול Redis מ- SQL Server, כאשר מרבית הפרוייקט זה סה”כ תפירה בין קוד C# קיים לעבודה מול Redis ל- SQL Server – שמתבצעת באמצעות SQL CLR, פיצ’ר חביב (למרות שהיה יכול להיות טוב משמעותית) שמאפשר לשלב ולכתוב רכיבים שונים בדטאבייס (functions, stored procedures וכו’) ב- C#.

הדרישה שהייתה לי לצרכי פיתוח הייתה פשוטה – שבסוף כל build יהיה לי קובץ install.sql שכשאני מריץ אותו הוא מכיל את כל ה- CREATE statements של ה- CLR functions / procedures שלי, ו- uninstall.sql שכולל את ה- DROP statements הרלוונטיים. הדבר העיקרי ממנו רציתי להימנע זה התענוג (המפוקפק) בלהכין create statements לכל פונקציה בנפרד, ואז כל פעם שמשנים במהלך הפיתוח את הפרמטרים לעדכן גם בקוד C# וגם בסקריפט ה-SQL-י ולייצר למעשה שכפול מיותר של הגדרות.… להמשך קריאה

SQL: להפוך XML במבנה לא ידוע (חלקית) לתצוגה טבלאית

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

למשל, אם אנחנו רוצים לשלוף מ- sys.tables ולהציג את התוצאות כ-XML בפורמט טבלאי, כל שצריך לעשות זה להוסיף FOR XML statement בסוף. ניתן בצורה הזאת גם להשיג שליטה מוגבלת על מבנה ה-XML שמתקבל. למשל, בדוגמא הבאה, אני מגדיר שיהיה root element בשם items ושכל שורה תהיה עטופה בתור item:

SELECT *

FROM sys.tables

FOR XML PATH('item'), ROOT('items')

ככה ייראה ה-XML שיתקבל:

image

אבל, מה קורה כשאנחנו רוצים להפוך את ה-XML הזה לתצורה טבלאית בחזרה? לצורך כך יש לנו את הפונקציה OPENXML.… להמשך קריאה