Menu

Funkcje tekstowe w SQLite: SUBSTR, REPLACE, INSTR i inne

Praktyczne funkcje tekstowe w SQLite: łączenie przez ||, SUBSTR, INSTR, REPLACE, TRIM oraz wzorce do czyszczenia i przekształcania tekstu w zapytaniach.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

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 start do końca.
  • Ujemny start liczy od końca napisu.
  • Jeśli start wypada 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; NULL psuje wynik, więc używaj COALESCE.
  • SUBSTR i INSTR razem pokrywają większość potrzeb typu „znajdź i wytnij”.
  • REPLACE zamienia każde wystąpienie dosłownego fragmentu.
  • TRIM i pokrewne funkcje przyjmują własny zbiór znaków, nie tylko białe znaki.
  • printf to właściwe narzędzie do sformatowanego wyniku.
  • LIKE do symboli wieloznacznych SQL bez rozróżniania wielkości liter, GLOB do 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.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ