Wszystkie zagadnienia: Bazy danych
średni SQLfunkcje tekstowePESELmatura rozszerzona z informatyki

Funkcje tekstowe i łączenie pól

Wycinanie fragmentów tekstu funkcjami Left, Right, Mid i Len oraz sklejanie pól w jedną kolumnę – z przykładami na numerze PESEL.

01

Opis

Część informacji siedzi w środku wartości tekstowej, a nie w osobnej kolumnie. Numer PESEL koduje datę urodzenia na konkretnych pozycjach, kod pocztowy zawiera numer rejonu, sygnatura sprawy – rok. Żeby zapytać o taki fragment, trzeba go najpierw wyciąć. Służą do tego funkcje tekstowe.

Wszystkie działają na tej samej zasadzie: dostają tekst i informację, którą część z niego wziąć, a zwracają sam wycięty fragment. Można ich używać zarówno na liście kolumn po SELECT (żeby fragment pokazać), jak i w warunku WHERE (żeby po nim filtrować).

Numerowanie znaków zaczyna się od 1, nie od 0. To najczęstsze źródło pomyłek u osób przyzwyczajonych do programowania, gdzie pierwszy element ma zwykle numer zero. W SQL-u pierwszy znak tekstu to znak numer 1.

Wycinanie ze środka wymaga dwóch liczb: od którego znaku zacząć i ile znaków wziąć. Dzień urodzenia w numerze PESEL zajmuje pozycje piątą i szóstą, więc parametry to „zacznij od 5, weź 2 znaki".

Wynik wycięcia jest tekstem, nie liczbą. Porównując go, trzeba użyć apostrofów – '05', a nie 05. To ma znaczenie także przy sortowaniu: teksty porównują się znak po znaku, więc '10' jest „mniejsze" niż '9'. Jeśli potrzebna jest liczba, trzeba wycięty fragment jawnie przekonwertować.

Łączenie pól w jedną kolumnę. Często wygodniej pokazać „Kowalska Anna" w jednej kolumnie niż nazwisko i imię w dwóch. Do sklejania tekstów służy operator łączenia – w Accessie jest to znak &, w standardowym SQL-u podwójna kreska pionowa. Sklejać można zarówno kolumny, jak i wpisane wprost napisy: żeby między nazwiskiem a imieniem pojawiła się spacja, trzeba ją dokleić jako osobny tekst ' '.

Kolumnie powstałej ze sklejenia trzeba nadać nazwę etykietą AS – inaczej nagłówek będzie nieczytelny.

Do wyszukiwania po wzorcu, a nie po konkretnej pozycji, lepiej nadaje się operator LIKE.

  • Numerowanie znaków od 1. Pierwszy znak tekstu to znak numer jeden, nie zero.
  • Wynik wycięcia jest zawsze tekstem. Porównuj go w apostrofach; do obliczeń przekonwertuj jawnie na liczbę.
  • Sklejona kolumna potrzebuje aliasu. Bez etykiety AS nagłówek wyniku jest nieczytelny.
  • Nazwy funkcji i operator sklejania są dialektem Accessa. W standardowym SQL-u część z nich nazywa się i zapisuje inaczej – patrz sekcja Dialekt.
02

Funkcje

Left(tekst; ile)
znaki od lewejZwraca zadaną liczbę pierwszych znaków tekstu.
Right(tekst; ile)
znaki od prawejTo samo, licząc od końca.
Mid(tekst; od; ile)
fragment ze środkaZaczyna od znaku o podanym numerze i bierze zadaną ich liczbę.
Len(tekst)
długośćZwraca liczbę znaków. Przydatne do sprawdzania poprawności długości numeru.
UCase(tekst)
wielkie literyZamienia wszystkie litery na wielkie, reszty znaków nie rusza.
LCase(tekst)
małe literyZamienia wszystkie litery na małe.
InStr(tekst; szukany)
pozycja wzorcaZwraca numer znaku, od którego zaczyna się pierwsze wystąpienie szukanego fragmentu, albo 0, gdy go nie ma.
Trim(tekst)
obcięcie spacjiUsuwa spacje z początku i z końca tekstu; spacji w środku nie rusza.
03

Dialekt

W AccessieStandardowy SQLZnaczenie
& (podwójna kreska pionowa) łączenie tekstów w jedną wartość
Mid(t; od; ile) SUBSTRING(t FROM od FOR ile) wycięcie fragmentu ze środka
Len(t) LENGTH(t) długość tekstu w znakach
UCase(t), LCase(t) UPPER(t), LOWER(t) zamiana wielkości liter
InStr(t; szukany) POSITION(szukany IN t) pozycja wzorca w tekście – kolejność argumentów jest odwrócona
04

Zapytanie

-- Rocznik z numeru PESEL: dwie pierwsze cyfry, wynik jako tekst
SELECT nazwisko, pesel
FROM uczniowie
WHERE Left(pesel; 2) = '07'
Wynik zapytania
nazwiskopesel
Kowalska07231212345
Wiśniewski07212812345
Dąbrowski07283012345
-- Dzień urodzenia siedzi na pozycjach 5-6 - stąd Mid od 5 na długość 2
SELECT nazwisko, Mid(pesel; 5; 2) AS dzien
FROM uczniowie
Wynik zapytania
nazwiskodzien
Kowalska12
Nowak05
Wiśniewski28
Zając19
Dąbrowski30
-- Pierwsza litera nazwiska: Left z jednym znakiem
SELECT Left(nazwisko; 1) AS inicjal, imie
FROM uczniowie
Wynik zapytania
inicjalimie
KAnna
NPiotr
WMarek
ZJulia
DKarol
-- Sklejanie pól i wpisanego wprost tekstu w jedną kolumnę
SELECT nazwisko & ' ' & imie AS kto, klasa
FROM uczniowie
Wynik zapytania
ktoklasa
Kowalska Anna3A
Nowak Piotr3B
Wiśniewski Marek3A
Zając Julia3C
Dąbrowski Karol3B
-- Surowy kod miesiąca z pozycji 3-4, bez korekty o 20 - patrz Protip niżej
SELECT nazwisko, Mid(pesel; 3; 2) AS kod_miesiaca
FROM uczniowie
Wynik zapytania
nazwiskokod_miesiaca
Kowalska23
Nowak31
Wiśniewski21
Zając25
Dąbrowski28
-- Len w warunku WHERE: tylko nazwiska dłuższe niż 8 znaków
SELECT nazwisko, Len(nazwisko) AS ile_znakow
FROM uczniowie
WHERE Len(nazwisko) > 8
Wynik zapytania
nazwiskoile_znakow
Wiśniewski10
Dąbrowski9
-- Przypadek brzegowy: warunek na literze, której nie ma na początku żadnego nazwiska
SELECT UCase(nazwisko) AS wielkimi
FROM uczniowie
WHERE Left(nazwisko; 1) = 'X'
Wynik zapytania
wielkimi
05

Typowe błędy

Liczenie znaków od zera. Ktoś, kto pamięta indeksowanie z Pythona, próbuje wyciąć dzień urodzenia zapisem Mid(pesel; 4; 2). To przesuwa wycięcie o jedną pozycję w lewo i zamiast dnia daje ostatnią cyfrę miesiąca sklejoną z pierwszą dnia – wynik wygląda jak liczba, więc błąd łatwo przeoczyć. Poprawnie: Mid(pesel; 5; 2), bo dzień zaczyna się na piątej pozycji.

Porównanie wyciętego fragmentu z liczbą bez apostrofów. Zapytanie WHERE Left(pesel; 2) = 07 zamiast = '07' w Accessie najczęściej zgłasza błąd typu danych, bo 07 jako liczba to po prostu 7, a Left zwraca tekst. Efekt bywa też cichszy: pusta tabela wyników bez żadnego komunikatu. Wynik funkcji tekstowej trzeba porównywać z tekstem w apostrofach.

Zapomniana korekta +20 przy miesiącu. WHERE Mid(pesel; 3; 2) = '05' ma znaleźć osoby urodzone w maju, ale dla roczników 2000+ maj zapisany jest jako 25. Zapytanie nie zwróci błędu – po prostu cicho pominie właściwe osoby i pokaże pustą albo niepełną tabelę. Trzeba sprawdzić, z jakiego rocznika są dane, i doliczyć 20 tam, gdzie trzeba.

Brak aliasu dla sklejonej kolumny. SELECT nazwisko & ' ' & imie FROM uczniowie policzy wynik poprawnie, ale nagłówkiem kolumny będzie coś w rodzaju Expr1000 – nazwa nadana automatycznie przez silnik, bezużyteczna dla czytającego. Lekarstwo to AS kto po wyrażeniu.

Użycie + zamiast & do sklejania w Accessie. SELECT nazwisko + ' ' + imie FROM uczniowie bywa mylone ze sklejaniem, bo w niektórych bazach + też łączy teksty. W Accessie, jeśli którakolwiek z kolumn ma wartość NULL, cały wynik sklejenia przez + staje się NULL – znika cały wiersz z sensownego wyniku, a & w tej samej sytuacji po prostu pominie brakujący fragment.

Pomylone kierunki Left i Right. Zapytanie o rocznik czasem pisane jest jako Right(pesel; 2) zamiast Left(pesel; 2) – zamiast dwóch pierwszych cyfr (rok) wychodzą dwie ostatnie (fragment numeru porządkowego). Wynik jest liczbą podobnej wielkości, więc błąd nie rzuca się w oczy, dopóki ktoś nie porówna go z metryką ucznia.

Oczekiwanie, że Trim usunie spacje w środku tekstu. Trim(' Anna Maria ') da Anna Maria – podwójna spacja między imionami zostaje, bo Trim obcina tylko początek i koniec. Do spacji w środku potrzebna jest inna technika (zamiana fragmentu), nie Trim.

06

Zapamiętaj

  • Pierwszy znak tekstu ma numer 1, nie 0.
  • Left(tekst; ile) i Right(tekst; ile) biorą znaki od początku i od końca; Mid(tekst; od; ile) wycina ze środka.
  • Wynik każdej funkcji tekstowej to tekst – porównuj go w apostrofach.
  • Sklejanie w Accessie robi znak &; w standardowym SQL-u podwójna kreska pionowa.
  • Sklejonej kolumnie zawsze nadaj alias przez AS, inaczej nagłówek będzie nieczytelny.
  • Trim usuwa spacje tylko z początku i końca tekstu, nie w środku.
  • W kluczach CKE 2015–2025 nie ma zapytań z Left, Mid, Right ani Len – ćwicz je jednak, bo mechanika wraca w Excelu.
07

Sprawdź się

Fragment tabeli uczniowie (tylko dwie kolumny potrzebne do ćwiczenia):

nazwiskopesel
Kowalska07231212345
Nowak06310512345
Wiśniewski07212812345
Zając06251912345
Dąbrowski07283012345

Uzupełnij odpowiedzi na podstawie tabeli:

PytanieOdpowiedź
Jaką wartość zwróci Left(pesel; 2) dla Nowaka?
Jaką wartość zwróci Mid(pesel; 5; 2) dla Zając?
Ile wierszy zwróci SELECT nazwisko FROM uczniowie WHERE Left(pesel; 2) = '06'?
Jaki znak sklejenia tekstów działa w Accessie?
Jaką wartość zwróci Len(nazwisko) dla Wiśniewski?
Jaką wartość zwróci UCase(nazwisko) dla Zając?
Który operator porównuje wynik funkcji tekstowej jako tekst, a nie liczbę?
Ile wierszy zwróci zapytanie z warunkiem Left(nazwisko; 1) = 'X'?

Zapytanie SELECT nazwisko, Mid(pesel; 3; 2) AS kod FROM uczniowie WHERE nazwisko = zwróci dla tego ucznia kod miesiąca równy , co po odjęciu daje prawdziwy numer miesiąca .

08

Najczęściej zadawane pytania

Czy da się wyciąć fragment i od razu potraktować go jak liczbę?

Tak, ale wymaga to jawnej konwersji – w Accessie funkcją zamieniającą tekst na liczbę całkowitą. Bez niej porównania będą tekstowe, co przy liczbach o różnej liczbie cyfr daje mylące wyniki.

Co się stanie, gdy poproszę o więcej znaków, niż tekst ma?

Funkcja nie zgłosi błędu – zwróci po prostu tyle, ile jest. Wycięcie 5 znaków z trzyliterowego tekstu da ten trzyliterowy tekst.

Czy funkcje tekstowe działają na kolumnach liczbowych?

Zwykle tak, bo baza najpierw zamienia liczbę na tekst. Bywa to jednak zawodne przy liczbach ułamkowych – zależy od tego, jak zostaną wypisane. Jeśli numer ma być cięty na fragmenty, lepiej przechowywać go od początku jako tekst.

Czym różni się InStr od Left i Mid?

Left i Mid wycinają fragment tekstu na podstawie podanej pozycji. InStr niczego nie wycina – szuka wzorca i zwraca numer pozycji, na której się zaczyna, albo 0, gdy go nie znajdzie. Często łączy się je: najpierw InStr znajduje miejsce, potem Mid wycina fragment od tego miejsca.

Co zwróci Left albo Mid dla pustego tekstu?

Pusty tekst, bez błędu. Jeśli natomiast argumentem jest wartość NULL, wynikiem funkcji też jest NULL – funkcje tekstowe nie zamieniają braku wartości w pusty napis.

Dlaczego sortowanie po wyciętym fragmencie wygląda dziwnie dla liczb?

Bo wynik funkcji tekstowej to tekst, a teksty sortują się znak po znaku, nie jak liczby. '10' w takim sortowaniu wypada przed '9', bo znak '1' jest „mniejszy" od '9'. Żeby posortować numerycznie, trzeba jawnie skonwertować wycięty fragment na liczbę.

Czy w standardowym SQL-u pozycje też liczy się od 1?

Tak, to akurat jest zgodne z Accessem – SUBSTRING również zaczyna liczenie znaków od 1. Różni się tylko składnia wywołania i nazwy funkcji, nie sam sposób numerowania.

Przećwicz w zadaniach maturalnych

Do tego hasła nie mamy jeszcze przypisanych pojedynczych zadań. Cały spis zadań maturalnych z tego działu jest tutaj:

Zadania z działu: SQL

↗

Powiązane zagadnienia