רוב השאילתות האמיתיות עוסקות במחרוזות
מספרים הם קלים. מחרוזות הן המקום שבו שאילתות מסתבכות: שמות עם רווחים מיותרים, כתובות אימייל באותיות מעורבות, מזהים שמודבקים יחד עם מקפים, שדות טקסט חופשי שכמעט תואמים אבל לא בדיוק. SQLite מגיע עם סט קטן וממוקד של פונקציות מחרוזת שמטפלות ברוב המקרים האלה בלי צורך בקוד אפליקציה.
הדף הזה עובר על הפונקציות שתשתמשו בהן ראשונות: שרשור, חיתוך, חיפוש, החלפה, קיצוץ רווחים ועיצוב.
שרשור משתמש ב-||, לא ב-CONCAT
ל-SQLite אין פונקציית CONCAT. מחרוזות מחוברות בעזרת האופרטור ||:
מספרים וטיפוסים אחרים מומרים לטקסט אוטומטית. המלכודת: אם אחד האופרנדים הוא NULL, כל הביטוי הופך ל-NULL. זו התנהגות SQL סטנדרטית, אבל היא מפתיעה אנשים:
עטפו עמודות שעשויות להכיל NULL ב-COALESCE(col, '') או ב-COALESCE(col, 'default') כשאתם רוצים שערך חסר לא ימחק את כל המחרוזת.
Length, Upper, Lower
שלוש הפונקציות שתשתמשו בהן כל הזמן:
LENGTH מחזירה את מספר התווים בטקסט, לא את מספר הבייטים. אם אתם באמת רוצים בייטים (נדיר, אבל שימושי לניתוח אחסון), השתמשו ב-OCTET_LENGTH. UPPER ו-LOWER משנות רק אותיות ASCII כברירת מחדל: תווים עם סימני הטעמה עוברים ללא שינוי, אלא אם טענתם את הרחבת ICU.
SUBSTR: חיתוך מחרוזות
SUBSTR(text, start, length) מחלצת חלק ממחרוזת. האינדקסים מתחילים מ-1: 1 הוא התו הראשון, לא 0:
כמה דברים שכדאי לזכור:
- הארגומנט השלישי אופציונלי. בלעדיו, מקבלים את כל מה שמ-
startועד הסוף. startשלילי נספר מסוף המחרוזת.- אם
startנמצא אחרי הסוף, מקבלים מחרוזת ריקה, לא שגיאה.
גם SUBSTRING מתקבלת כשם נרדף, למקרה שהזיכרון של האצבעות שלכם מגיע ממסד נתונים אחר.
INSTR: מציאת תת מחרוזת
INSTR(haystack, needle) מחזירה את המיקום (החל מ-1) של ההופעה הראשונה של needle בתוך haystack, או 0 אם היא לא נמצאה:
הביטוי האחרון הוא הדרך המקובלת ב-SQLite לקבל "כל מה שלפני ה-@": מוצאים את התו המפריד עם INSTR, ואז חותכים עם SUBSTR. תכתבו את השילוב הזה הרבה. שימו לב שמכיוון ש-INSTR מחזירה 0 כשאין התאמה, כדאי לבדוק לפני החיתוך: העברת 0 ל-SUBSTR נותנת בשקט תוצאות מוזרות.
REPLACE: החלפת תת מחרוזת אחת באחרת
REPLACE(text, old, new) מחליפה כל הופעה של old ב-new:
היא רגישה לאותיות גדולות וקטנות ולא מקבלת ביטוי רגולרי, רק תת מחרוזת מילולית. לשינויים מורכבים יותר אפשר לשרשר קריאות REPLACE, אבל אחרי שתיים או שלוש קריאות מקוננות הגיע הזמן לעשות את העבודה באפליקציה.
TRIM, LTRIM, RTRIM
נתונים שמשתמשים מקלידים נוטים להגיע עם רווחים בקצוות. TRIM מסירה אותם:
כברירת מחדל הן מסירות רווחים. העבירו ארגומנט שני כדי לקבוע אילו תווים להסיר: כל תו בארגומנט השני נחשב חבר ב"קבוצת תווים להסרה", ולא כתת מחרוזת מילולית. כך TRIM('xxxhelloxx', 'x') נותנת 'hello'.
printf: עיצוב מספרים ומחרוזות
כשצריך מחרוזת מעוצבת, כמו מספר קבוע של ספרות אחרי הנקודה, מספרים עם ריפוד או פלט הקסדצימלי, printf (שנכתבת גם format) עושה את העבודה:
מצייני העיצוב פועלים לפי המוסכמות של C, כלומר %d, %s, %f, %x, ריפוד באפסים או ברווחים, וכן הלאה. זה נקי בהרבה מבניית מחרוזות עם || וערימה של CAST.
LIKE מול GLOB: התאמת תבניות
שני אופרטורים, שני עולמות שונים.
LIKE משתמש בתווים הכלליים הקלאסיים של SQL, % לכל רצף תווים ו-_ לתו בודד, והוא לא רגיש לאותיות גדולות וקטנות ב-ASCII:
GLOB משתמש בתווים הכלליים של מעטפת Unix, * לכל רצף, ? לתו בודד ו-[abc] למחלקות תווים, והוא רגיש לאותיות גדולות וקטנות:
הכלל לבחירה ביניהם: LIKE להתאמה בסגנון אנושי כמו "מתחיל ב", "מכיל", "מסתיים ב". GLOB כשרגישות לאותיות חשובה או כשצריך מחלקות תווים. שניהם יכולים להשתמש באינדקסים, אבל רק כשהתבנית מעוגנת להתחלה ('foo%', לא '%foo'): תו כללי בהתחלה מאלץ סריקה מלאה.
פיצול מחרוזות: אין SPLIT
SQLite לא מגיע עם פונקציית SPLIT_STRING. שני פתרונות מעשיים:
לפיצול לפי תו מפריד לכמה שורות, הדרך הנקייה ביותר היא json_each על מערך JSON, או CTE רקורסיבי. נכסה את שניהם בפרקים הבאים. בינתיים, פשוט דעו ש"תן לי כל מילה" היא לא שורה אחת ב-SQLite.
דוגמה מעשית: ניקוי שמות
נחבר הכול יחד. דמיינו טבלת users עם שמות תצוגה מבולגנים: רווחים מיותרים, אותיות מעורבות ותארים אופציונליים כמו "Dr. " או "Mr. " שתרצו להסיר:
קוראים את הביטוי מבפנים החוצה: מסירים רווחים חיצוניים, ממירים לאותיות קטנות, מוחקים את התארים, ומקצצים שוב למקרה שהסרת התואר השאירה רווח בהתחלה. כל שלב הוא פונקציה אחת: המורכבות נובעת מהערימה שלהן. כשהערימה עוברת שלוש או ארבע רמות, זה רמז להשתמש בעמודה מחושבת (פרק: תכונות מתקדמות) או לבצע את הניקוי בזמן ייבוא הנתונים.
מה לקחת מכאן
||לשרשור.NULLמרעיל את התוצאה, אז השתמשו ב-COALESCE.SUBSTRו-INSTRיחד מכסות את רוב הצרכים של "מצא וחתוך".REPLACEמחליפה כל הופעה של תת מחרוזת מילולית.TRIMוהפונקציות הדומות לה מקבלות קבוצת תווים מותאמת, לא רק רווחים.printfהיא הכלי הנכון לפלט מעוצב.LIKEלתווים כלליים של SQL ללא רגישות לאותיות,GLOBלתבניות בסגנון מעטפת עם רגישות לאותיות.
הבא בתור: פונקציות מספריות
אחרי המחרוזות, התחנה הבאה הטבעית היא מספרים: עיגול, ערכים מוחלטים, מוזרויות של חילוק, ופונקציות המתמטיקה ש-SQLite הוסיף בגרסאות האחרונות. זה הדף הבא.
שאלות נפוצות
איך משרשרים מחרוזות ב-SQLite?
משתמשים באופרטור ||, לא ב-CONCAT. ל-SQLite אין פונקציית CONCAT כברירת מחדל: 'Hello, ' || name מחבר שתי מחרוזות לאחת. אם אחד האופרנדים הוא NULL, כל התוצאה היא NULL, ולכן עטפו עמודות שעשויות להכיל NULL ב-COALESCE כשזו לא ההתנהגות שאתם רוצים.
איך מחלצים תת מחרוזת ב-SQLite?
השתמשו ב-SUBSTR(text, start, length), שנכתבת גם SUBSTRING. האינדקסים מתחילים מ-1: SUBSTR('hello', 1, 3) מחזירה 'hel'. נקודת התחלה שלילית נספרת מהסוף, והארגומנט של האורך אופציונלי: השמיטו אותו כדי לקבל את כל מה שעד הסוף.
האם יש ל-SQLite פונקציית SPLIT_STRING?
לא, ל-SQLite אין פונקציית פיצול מובנית. ברוב המקרים אפשר לשלב את INSTR ו-SUBSTR כדי לחלץ את החלק הרצוי, או להשתמש ב-CTE רקורסיבי כדי לפצל לפי תו מפריד. אם צריך את זה לעיתים קרובות, הפונקציה json_each על מערך JSON בדרך כלל נקייה יותר מלכתוב מפצל משלכם.
מה ההבדל בין LIKE ל-GLOB ב-SQLite?
LIKE לא רגיש לאותיות גדולות וקטנות ב-ASCII כברירת מחדל, ומשתמש ב-% וב-_ כתווים כלליים. GLOB רגיש לאותיות גדולות וקטנות ומשתמש בתווים הכלליים של מעטפת Unix (*, ?, [abc]). בחרו ב-GLOB כשצריך רגישות לאותיות או מחלקות תווים, וב-LIKE להתאמה המוכרת בסגנון SQL.