View הוא שאילתה שמורה
View הוא פקודת SELECT עם שם. אחרי שיצרתם אחד, אפשר לשאול אותו כמו טבלה, אבל שום דבר לא נשמר. בכל פעם שקוראים מ-view, SQLite מריץ את השאילתה שמתחתיו מחדש.
paid_orders נראה ומתנהג כמו טבלה. יש לו עמודות, אפשר לבצע עליו SELECT, אפשר לעשות איתו join. אבל מתחת למכסה המנוע, כל שאילתה נפרשת לסינון המקורי WHERE status = 'paid'.
זה כל המודל המנטלי: view הוא כינוי לשאילתה.
למה Views שימושיים
היתרון העיקרי הוא מתן שם. שאילתה מסובכת מקבלת שם קצר ותיאורי, ושאר הקוד שלכם נשאר קריא:
בלי ה-view, כל קוד קורא היה כותב את ה-GROUP BY בעצמו, וכל אחד מהם היה יכול לטעות בסינון. איתו, הצבירה מוגדרת פעם אחת. הקוראים פשוט מבקשים את customer_totals ומוסיפים מעליו כל סינון נוסף שהם צריכים.
Views עובדים גם כגבול בסגנון הרשאות. אם שאילתה לא אמורה לחשוף עמודת password_hash, בנו view שבוחר הכול חוץ מהעמודה הזו, ותנו לקוד האפליקציה להשתמש ב-view.
התחביר של CREATE VIEW
הצורה המלאה:
CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name [(column_aliases)] AS
SELECT ...;
כמה דברים שכדאי לדעת:
IF NOT EXISTSמדלג בשקט על היצירה אם ה-view כבר קיים.TEMPORARY(אוTEMP) יוצר view שנעלם כשהחיבור נסגר.- כינויי עמודות בסוגריים מאפשרים לשנות את שמות העמודות של ה-view בלי לגעת ב-
SELECTשמתחתיו.
ה-view חושף שמות ידידותיים יותר (item, dollars) בלי לשנות את שמות העמודות בטבלת המקור.
החלפה ומחיקה של Views
ל-SQLite אין CREATE OR REPLACE VIEW או ALTER VIEW. כדי לשנות את ההגדרה של view, מחקו אותו וצרו אותו מחדש:
DROP VIEW IF EXISTS active_orders; היא הצורה הבטוחה: היא לא תיכשל אם ה-view לא קיים. מחיקת view אף פעם לא משפיעה על הטבלאות שמתחתיו: אתם מוחקים רק את השאילתה השמורה.
Views זמניים
TEMP VIEW קיים רק עבור החיבור הנוכחי למסד הנתונים. כשהחיבור נסגר, ה-view נעלם. שימושי לסשנים של ניתוח אד הוק שבהם אתם לא רוצים להשאיר הגדרות מאחור:
Views זמניים גם מאפשרים לתת לשאילתה שם זמני, אפילו כזה שמסתיר שם קיים, בלי להתחייב אליו בסכמה, וזה נוח בזמן חקירה.
Views הם לקריאה בלבד כברירת מחדל
זו המלכודת החשובה ביותר. אי אפשר לבצע INSERT, UPDATE או DELETE דרך view ישירות:
sqlite> INSERT INTO paid_orders (customer, amount) VALUES ('Eve', 50);
Runtime error: cannot modify paid_orders because it is a view
הפתרון הוא טריגרים של INSTEAD OF. כותבים טריגר שמופעל במקום ניסיון הכתיבה ומתרגם אותו לפעולה אמיתית על הטבלה שמתחת:
ה-view נשאר view, אבל לכתיבות אליו יש עכשיו לאן ללכת. נכסה טריגרים כמו שצריך בדף הבא.
אין Materialized Views: בנו בעצמכם
חלק ממסדי הנתונים מאפשרים לשמור את התוצאות של view על הדיסק ולרענן אותן לפי דרישה. SQLite לא. כל קריאה מ-view מריצה מחדש את השאילתה שמתחתיו. לרוב העומסים זה בסדר: SQLite מהיר ומתכנן השאילתות טוב. לצבירות יקרות שנשאלות פעמים רבות, בנו טבלה אמיתית ושמרו אותה מסונכרנת בעצמכם:
אחר כך תרעננו את המטמון לפי לוח זמנים, או תחברו טריגרים על orders כדי לשמור אותו עדכני. זו עבודה ידנית, אבל זו גם האפשרות היחידה ב-SQLite.
הצגת Views
המטא דאטה של views נשמר ב-sqlite_master לצד טבלאות ואינדקסים:
העמודה sql מחזירה את פקודת ה-CREATE VIEW המקורית: שימושי כששכחתם מה view עושה. ב-CLI, .schema view_name מדפיס את אותו הדבר בצורה נקייה יותר.
מתי לפנות ל-View
Views מצדיקים את עצמם כאשר:
- שאילתה לא טריוויאלית נמצאת בשימוש בשלושה מקומות או יותר. לתת לה שם פעם אחת עדיף על העתקה והדבקה.
- רוצים לחשוף תת קבוצה מוקפדת של עמודות או שורות לחלק מהאפליקציה.
- צבירה היא מבחינה רעיונית דבר אחד (
monthly_sales,active_users) שהקוראים צריכים להתייחס אליו כשם עצם.
וותרו על ה-view כאשר:
- השאילתה משמשת במקום אחד בדיוק. כתבו אותה ישירות.
- הביצועים חשובים והשאילתה שמתחת יקרה: אתם משלמים את המחיר הזה בכל קריאה. שמרו במקום זאת במטמון בטבלה אמיתית.
- ה-view תלוי ב-view אחר שתלוי ב-view אחר. SQLite מטפל בקינון היטב, אבל שרשרת של שלושה או ארבעה views הופכת את ה-SQL האמיתי לקשה למעקב בזמן דיבוג.
הבא בתור: טריגרים
Views וטריגרים מופיעים יחד הרבה: תבנית ה-INSTEAD OF שמאפשרת לכתוב ל-views היא אחת הסיבות העיקריות לקיומם של טריגרים. טריגרים שימושיים גם בפני עצמם ליומני ביקורת, לעדכונים מתגלגלים ולאכיפת אינווריאנטים. זה הדף הבא.
שאלות נפוצות
מה זה view ב-SQLite?
View הוא פקודת SELECT שמורה שאפשר לשאול אותה כמו טבלה. הוא לא שומר נתונים: בכל פעם שקוראים ממנו, SQLite מריץ מחדש את השאילתה שמתחתיו. Views שימושיים כדי לתת שם לשאילתה מורכבת פעם אחת ולהשתמש בה בכל מקום, או כדי להסתיר עמודות שקוראים לא אמורים לראות.
האם אפשר לבצע INSERT או UPDATE דרך view ב-SQLite?
לא ישירות. Views ב-SQLite הם לקריאה בלבד: INSERT, UPDATE ו-DELETE מול view ייכשלו. אפשר לאפשר כתיבה ל-view על ידי צירוף טריגרים של INSTEAD OF שמתרגמים את הכתיבה לפעולות על הטבלאות שמתחתיו.
האם SQLite תומך ב-materialized views?
לא. ל-SQLite יש רק views רגילים (וירטואליים): השאילתה רצה בכל פעם שקוראים מה-view. אם צריך תוצאות שמורות במטמון, צרו טבלה אמיתית ורעננו אותה בעצמכם, או השתמשו בטריגר כדי לשמור אותה מסונכרנת עם טבלאות המקור.
איך מציגים את כל ה-views במסד נתונים של SQLite?
שאלו את sqlite_master: SELECT name FROM sqlite_master WHERE type = 'view';. ב-CLI, .schema מציג את פקודות ה-CREATE VIEW, ו-.tables מציג views לצד טבלאות.