Większość prawdziwych zapytań kręci się wokół tekstu
Liczby są proste. Problemy zaczynają się przy tekście: imiona z przypadkowymi spacjami, adresy e-mail pisane raz wielkimi, raz małymi literami, identyfikatory sklejone myślnikami, pola z wolnym tekstem, które pasują prawie, ale nie do końca. SQLite ma niewielki, konkretny zestaw funkcji tekstowych, który radzi sobie z większością takich przypadków bez kodu aplikacji.
Na tej stronie omawiamy te, po które sięgniesz najpierw: łączenie, wycinanie, wyszukiwanie, zamianę, przycinanie i formatowanie.
Łączenie napisów to ||, a nie CONCAT
SQLite nie ma funkcji CONCAT. Napisy łączy się operatorem ||:
Liczby i inne typy są automatycznie zamieniane na tekst. Haczyk: jeśli którykolwiek operand to NULL, całe wyrażenie staje się NULL. To standardowe zachowanie SQL, ale wiele osób zaskakuje:
Owiń kolumny, które mogą być puste, w COALESCE(col, '') albo COALESCE(col, 'default'), jeśli brakująca wartość nie ma zniszczyć całego napisu.
LENGTH, UPPER, LOWER
Te trzy funkcje będziesz używać bez przerwy:
LENGTH zwraca liczbę znaków tekstu, a nie bajtów. Jeśli naprawdę potrzebujesz bajtów (rzadko, ale przydaje się przy analizie rozmiaru danych), użyj OCTET_LENGTH. UPPER i LOWER domyślnie zmieniają tylko litery ASCII: znaki z akcentami przechodzą bez zmian, chyba że załadujesz rozszerzenie ICU.
SUBSTR: wycinanie fragmentów napisu
SUBSTR(text, start, length) wyciąga fragment napisu. Indeksy zaczynają się od 1: 1 to pierwszy znak, a nie 0:
Kilka rzeczy, o których warto pamiętać:
- Trzeci argument jest opcjonalny. Bez niego dostajesz wszystko od
startdo końca. - Ujemny
startliczy od końca napisu. - Jeśli
startwypada za końcem napisu, dostajesz pusty napis, a nie błąd.
SUBSTRING działa jako synonim, na wypadek gdyby twoje nawyki pochodziły z innej bazy danych.
INSTR: szukanie fragmentu
INSTR(haystack, needle) zwraca pozycję (liczoną od 1) pierwszego wystąpienia needle w haystack albo 0, jeśli nic nie znaleziono:
Ostatnie wyrażenie to typowy w SQLite sposób na „wszystko przed @”: znajdź separator przez INSTR, a potem wytnij fragment przez SUBSTR. To połączenie będziesz pisać często. Zwróć uwagę, że INSTR zwraca 0, gdy nic nie pasuje, więc sprawdź to przed wycinaniem: podanie 0 do SUBSTR po cichu daje dziwne wyniki.
REPLACE: zamiana jednego fragmentu na inny
REPLACE(text, old, new) zamienia każde wystąpienie old na new:
Funkcja rozróżnia wielkość liter i nie przyjmuje wyrażeń regularnych, tylko dosłowny fragment tekstu. Przy bardziej złożonych przekształceniach możesz łączyć kolejne wywołania REPLACE, ale gdy zagnieżdżasz ich więcej niż dwa czy trzy, czas przenieść tę pracę do aplikacji.
TRIM, LTRIM, RTRIM
Dane wpisywane przez użytkowników często mają spacje na początku i na końcu. TRIM je usuwa:
Domyślnie funkcje usuwają spacje. Podaj drugi argument, żeby wskazać, które znaki usunąć: każdy znak z drugiego argumentu jest traktowany jako element „zbioru do usunięcia”, a nie jako dosłowny fragment. Dlatego TRIM('xxxhelloxx', 'x') daje 'hello'.
printf: formatowanie liczb i napisów
Gdy potrzebujesz sformatowanego napisu (stała liczba miejsc po przecinku, liczby z zerami wiodącymi, zapis szesnastkowy), użyj printf (dostępnej też jako format):
Specyfikatory formatu działają jak w C, czyli %d, %s, %f, %x, dopełnianie zerami lub spacjami i tak dalej. To dużo czytelniejsze niż budowanie napisów przez || i stos CASTów.
LIKE vs GLOB: dopasowywanie wzorców
Dwa operatory, dwa różne światy.
LIKE używa klasycznych symboli wieloznacznych SQL: % oznacza dowolny ciąg znaków, _ pojedynczy znak. Nie rozróżnia wielkości liter dla ASCII:
GLOB używa symboli z powłoki Unix: * oznacza dowolny ciąg, ? pojedynczy znak, [abc] klasę znaków. Rozróżnia wielkość liter:
Zasada wyboru: LIKE do dopasowań w ludzkim stylu, takich jak „zaczyna się od”, „zawiera”, „kończy się na”. GLOB, gdy liczy się wielkość liter albo potrzebujesz klas znaków. Oba mogą korzystać z indeksów, ale tylko wtedy, gdy wzorzec jest zakotwiczony na początku ('foo%', a nie '%foo'): symbol wieloznaczny na początku wymusza pełne skanowanie.
Dzielenie napisów: SPLIT nie istnieje
SQLite nie ma funkcji SPLIT_STRING. Są dwa praktyczne obejścia:
Aby podzielić tekst według separatora na wiele wierszy, najczytelniej jest użyć json_each na tablicy JSON albo rekurencyjnego CTE. Oba sposoby omówimy w kolejnych rozdziałach. Na razie zapamiętaj, że „daj mi każde słowo” nie jest w SQLite jednolinijkowcem.
Przykład w praktyce: porządkowanie imion
Złóżmy to razem. Wyobraź sobie tabelę users z nieuporządkowanymi nazwami wyświetlanymi: nadmiarowe spacje, pomieszana wielkość liter, opcjonalne tytuły w rodzaju "Dr. " albo "Mr. ", które chcesz usunąć:
Wyrażenie czyta się od środka: usuń spacje z brzegów, zamień na małe litery, usuń tytuły, a potem przytnij jeszcze raz na wypadek, gdyby po usunięciu tytułu została spacja na początku. Każdy krok to jedna funkcja: złożoność bierze się z ich nakładania. Gdy stos rośnie ponad trzy czy cztery poziomy, to znak, żeby użyć kolumny generowanej (rozdział: funkcje zaawansowane) albo czyścić dane podczas importu.
Co warto zapamiętać
||do łączenia napisów;NULLpsuje wynik, więc używajCOALESCE.SUBSTRiINSTRrazem pokrywają większość potrzeb typu „znajdź i wytnij”.REPLACEzamienia każde wystąpienie dosłownego fragmentu.TRIMi pokrewne funkcje przyjmują własny zbiór znaków, nie tylko białe znaki.printfto właściwe narzędzie do sformatowanego wyniku.LIKEdo symboli wieloznacznych SQL bez rozróżniania wielkości liter,GLOBdo wzorców w stylu powłoki z rozróżnianiem wielkości liter.
Dalej: funkcje liczbowe
Skoro tekst mamy za sobą, naturalnym kolejnym krokiem są liczby: zaokrąglanie, wartości bezwzględne, pułapki dzielenia i funkcje matematyczne dodane w nowszych wersjach SQLite. O tym jest następna strona.
Najczęściej zadawane pytania
Jak połączyć napisy w SQLite?
Użyj operatora ||, a nie CONCAT. SQLite domyślnie nie ma funkcji CONCAT: 'Hello, ' || name łączy dwa napisy w jeden. Jeśli którykolwiek operand to NULL, cały wynik też jest NULL, więc owiń kolumny, które mogą być puste, w COALESCE, gdy nie chcesz takiego zachowania.
Jak wyciąć fragment napisu w SQLite?
Użyj SUBSTR(text, start, length), dostępnej też jako SUBSTRING. Indeksy zaczynają się od 1: SUBSTR('hello', 1, 3) zwraca 'hel'. Ujemny start liczy od końca, a argument długości jest opcjonalny: jeśli go pominiesz, dostaniesz wszystko do końca napisu.
Czy SQLite ma funkcję SPLIT_STRING?
Nie, SQLite nie ma wbudowanej funkcji do dzielenia napisów. W większości przypadków wystarczy połączyć INSTR i SUBSTR, żeby wyciągnąć potrzebny fragment, albo użyć rekurencyjnego CTE, żeby podzielić tekst według separatora. Jeśli robisz to często, json_each na tablicy JSON zwykle jest czytelniejsze niż własna funkcja dzieląca.
Czym różni się LIKE od GLOB w SQLite?
LIKE domyślnie nie rozróżnia wielkości liter dla ASCII i używa % oraz _ jako symboli wieloznacznych. GLOB rozróżnia wielkość liter i korzysta z symboli z powłoki Unix (*, ?, [abc]). Sięgnij po GLOB, gdy potrzebujesz rozróżniania wielkości liter albo klas znaków, a po LIKE przy bardziej znanym dopasowaniu w stylu SQL.