Menu

פסוקית RETURNING ב-SQLite: קבלת שורות מ-INSERT, UPDATE ו-DELETE

איך פסוקית RETURNING עובדת ב-SQLite: שליפת השורות שה-INSERT, ה-UPDATE או ה-DELETE שלכם שינו עכשיו, בלי שאילתה שנייה.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

דרך לראות מה קרה הרגע

כשמריצים INSERT, UPDATE או DELETE, SQLite אומרת לכם כמה שורות הושפעו, אבל לא אילו שורות, או איך נראים הערכים הסופיים שלהן. הפתרון הקלאסי הוא SELECT נוסף אחר כך. זה שתי פניות, שתי פקודות, וחלון זמן קטן שבו מישהו אחר יכול לשנות את השורה ביניהן.

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

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

RETURNING נוספה ב-SQLite 3.35.0 (מרץ 2021). אם הפקודה שלכם נדחית כשגיאת תחביר, בדקו עם SELECT sqlite_version();: גרסאות ישנות לא מכירות את מילת המפתח.

קבלת המזהה שנוצר

הסיבה הנפוצה ביותר להשתמש ב-RETURNING היא לקחת את המפתח הראשי שנוצר אוטומטית מיד אחרי ההכנסה:

לפני RETURNING, הייתם מכניסים ואז קוראים ל-last_insert_rowid() (או למקבילה בדרייבר שלכם) על אותו חיבור. זה עדיין עובד, אבל זה קסם של מצב החיבור: קל לטעות בו עם מאגרי חיבורים או תהליכונים. RETURNING id מפורש, מקומי לפקודה, ועובד אותו דבר לא משנה מה מחזיק את החיבור.

אם הטבלה שלכם לא מצהירה על INTEGER PRIMARY KEY מפורש, עדיין אפשר לקבל את מזהה השורה המובלע:

לכל טבלת SQLite רגילה יש rowid, ו-RETURNING תחזיר אותו.

כמה עמודות וביטויים

RETURNING מקבלת את אותה צורה כמו רשימת העמודות של SELECT. רשמו עמודות, השתמשו ב-*, בנו ביטויים, תנו להם כינויים:

RETURNING * שימושית כשרוצים הכול, כולל ברירות מחדל שמסד הנתונים מילא, בלי לקרוא בשם לכל עמודה:

רואים את ה-id החדש, את ה-name שהעברתם ואת חותמת הזמן ש-SQLite חישבה.

RETURNING עם UPDATE

ב-UPDATE, RETURNING נותנת את הערכים שאחרי העדכון: השורה כפי שהיא נראית אחרי שהשינויים שלכם הוחלו:

מקבלים בחזרה את היתרה החדשה של Ada, 125, ולא את הישנה, 100. זה הופך את RETURNING למושלמת למונים אטומיים ולפעולות זיכוי וחיוב: לא צריך לקרוא, לחשב, לכתוב ולקרוא שוב.

אם ה-WHERE מתאים לכמה שורות, מקבלים שורה אחת בחזרה לכל שורה שהושפעה:

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

RETURNING עם DELETE

ב-DELETE, RETURNING נותנת את השורות כפי שהיו רגע לפני המחיקה. שימושי לארכוב, לתיעוד ביקורת, או פשוט לאישור של מה שהוסר:

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

RETURNING עם UPSERT

RETURNING עובדת גם עם INSERT ... ON CONFLICT ... DO UPDATE. השורה שחוזרת משקפת את הענף שרץ: ההכנסה החדשה או העדכון בעקבות ההתנגשות:

הריצו את הפקודה פעמיים. בפעם הראשונה היא מכניסה ומחזירה ('visits', 1). בפעם השנייה ההתנגשות מופעלת, הערך גדל, ומקבלים בחזרה ('visits', 2). בכל מקרה, פקודה אחת ושורה אחת בפלט: אין צורך לשאול "האם זה הכניס או עדכן?" לפני שממשיכים.

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

כמה דברים שכדאי לדעת

כמה פרטים שמפתיעים אנשים:

  • RETURNING תמיד רואה את השורה אחרי השינוי ב-INSERT וב-UPDATE, ו_לפני_ השינוי ב-DELETE. אין תחביר לבקש את הצד השני.
  • סדר השורות שחוזרות אינו מובטח. הוסיפו ORDER BY בצד הלקוח אם זה חשוב.
  • אי אפשר לשים RETURNING בתוך תת-שאילתה. זו פסוקית ברמה העליונה של פקודת הכתיבה, לא ביטוי.
  • RETURNING לא מחזירה נתונים ששונו על ידי טריגרים מסוג BEFORE: היא מחזירה את הערכים שבאמת נכתבו. טריגרים מסוג AFTER רצים בין הכתיבה לבין החזרת השורה.
  • עמודות מחושבות וערכי DEFAULT נראים בתוצאה. זו בדיוק הסיבה ש-RETURNING * היא דרך מהירה לבדוק מה מסד הנתונים מילא בשבילכם.

הבא: ייבוא נתוני CSV

RETURNING מצוינת כשכותבים שורה אחת או כמה בכל פעם ורוצים לראות את התוצאה מיד. כשטוענים אלפי שורות מקובץ, משתמשים במקום זה בכלי ייבוא ה-CSV של SQLite, וזה העמוד הבא.

שאלות נפוצות

האם SQLite תומכת בפסוקית RETURNING?

כן, מגרסה 3.35.0 (שיצאה במרץ 2021). אפשר להוסיף RETURNING לפקודות INSERT, UPDATE ו-DELETE כדי לקבל בחזרה את השורות שהושפעו. אם אתם על SQLite ישנה יותר, המנתח ידחה את זה: בדקו עם SELECT sqlite_version();.

איך מקבלים את ה-ID של שורה שהרגע הכנסתי ב-SQLite?

השתמשו ב-INSERT ... RETURNING id (או RETURNING rowid אם לטבלה אין מפתח ראשי מפורש). זה מחזיר את הערך שנוצר כחלק מאותה פקודה, כך שלא צריך שאילתה שנייה כמו last_insert_rowid().

האם RETURNING יכולה להחזיר יותר מעמודה אחת?

כן. רשמו את העמודות שאתם רוצים מופרדות בפסיקים, בדיוק כמו ב-SELECT: RETURNING id, name, created_at. אפשר גם להשתמש ב-RETURNING * כדי לקבל כל עמודה, או לכתוב ביטויים כמו RETURNING id, price * quantity AS total.

האם RETURNING עובדת עם UPSERT ו-ON CONFLICT?

כן. INSERT ... ON CONFLICT ... DO UPDATE ... RETURNING ... מחזירה את השורה בין אם היא הוכנסה עכשיו ובין אם עודכנה בפתרון ההתנגשות. זו הדרך הנקייה ביותר לבצע upsert ולקרוא את המצב שנוצר בפנייה אחת.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל