Daty, CAST, CASE i COALESCE
Obliczaj terminy, konwertuj wartości i buduj wynik zależny od warunków. Porównaj daty i obsługę NULL w różnych bazach.
Część bazodanowa INF.03Data, jej zapis i strefa czasowa
Data 2026-02-03, znacznik czasu 2026-02-03 14:30:00 oraz napis „3 lutego” reprezentują różne informacje. W serwerze dobieraj typ DATE, DATETIME lub odpowiednik do celu. Nie przechowuj gotowego opisu dla człowieka zamiast daty, jeśli masz ją porównywać i obliczać terminy. W ćwiczeniach SQLite kolumna data jest tekstem ISO YYYY-MM-DD; jej format jest jednolity, a funkcje dat interpretują ten tekst.
„Teraz” może oznaczać czas serwera, sesji lub UTC. CURDATE()/NOW() w MySQL, GETDATE()/SYSUTCDATETIME() w SQL Server, SYSDATE/CURRENT_TIMESTAMP w Oracle i Date()/Now() w Access nie są uniwersalnymi zamiennikami. W zadaniach poniżej celowo używamy stałych dat, aby wynik był odtwarzalny niezależnie od dnia nauki.
To samo zadanie: termin siedem dni później
-- MySQL / MariaDB
SELECT id, DATE_ADD(data, INTERVAL 7 DAY) AS termin FROM zamowienia;
-- SQL Server
SELECT id, DATEADD(day, 7, data) AS termin FROM zamowienia;
-- Oracle 19c: data jest typu DATE
SELECT id, data + 7 AS termin FROM zamowienia;
-- Access: data jest typu Date/Time
SELECT id, DateAdd('d', 7, data) AS termin FROM zamowienia;
-- SQLite: dane tekstowe ISO z naszej bazy
SELECT id, DATE(data, '+7 days') AS termin FROM zamowienia ORDER BY id;Oczekiwane daty dla id 1–4: 2026-01-17, 2026-01-18, 2026-02-08, 2026-02-10. Format wyświetlenia w serwerze może być inny. Miesiąc nie ma stałej liczby dni, dlatego dodanie 30 dni nie zastępuje dodania miesiąca. Sprawdź reguły końca miesiąca, roku przestępnego oraz strefy czasowej.
Rok i różnica dni
| Cel | MySQL / MariaDB | SQL Server | Oracle 19c | Access | SQLite |
|---|---|---|---|---|---|
| Rok daty d | YEAR(d) | YEAR(d) | EXTRACT(YEAR FROM d) | Year(d) | CAST(STRFTIME(’%Y’,d) AS INTEGER) |
| Dni między a i b | DATEDIFF(b,a) | DATEDIFF(day,a,b) | b-a dla DATE | DateDiff(’d’,a,b) | JULIANDAY(b)-JULIANDAY(a) |
Ostatni wiersz porównuje zastosowanie, ale nie obiecuje identycznego wyniku dla znaczników czasu. MySQL DATEDIFF pomija część czasową. SQL Server liczy przekroczenia granicy jednostki: chwila przed północą i chwila po niej dają DATEDIFF(day,…)=1, choć nie upłynęła doba. Oracle DATE odejmowane od DATE daje liczbę dni z częścią ułamkową; timestamp może dać interwał. SQLite JULIANDAY także może dać ułamek. Sama różnica numerów lat nie jest dokładnym wiekiem osoby.
-- Natywny SQLite
SELECT JULIANDAY('2026-02-03') - JULIANDAY('2026-02-01') AS dni;
SELECT id, CAST(STRFTIME('%m', data) AS INTEGER) AS miesiac
FROM zamowienia ORDER BY id;Wyniki: 2 dni oraz miesiące 1, 1, 2, 2. Funkcja STRFTIME zwraca tekst; CAST zamienia miesiąc na liczbę. Wbudowany edytor wykonuje natywne funkcje SQLite, a DATEDIFF/DATEADD/EXTRACT z serwerów nie są emulowane. Tryby MySQL i SQL Server obsługują jedynie proste YEAR/MONTH/DAY dla poprawnych dat ISO.
Wypróbuj zapytanie
SQLite — rzeczywisty silnik przeglądarki. MySQL / SQL Server — ograniczona emulacja składni. Wybierz tryb SQLite do natywnego LIKE. Pozostałe tryby nie są rzeczywistymi serwerami. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.
CAST: jawnie powiedz, jakiej wartości potrzebujesz
-- SQLite
SELECT CAST('42' AS INTEGER) + 1 AS nastepna;
-- MySQL / MariaDB
SELECT CAST('42' AS SIGNED) + 1 AS nastepna;
-- SQL Server
SELECT CAST('42' AS int) + 1 AS nastepna;
-- Oracle 19c
SELECT CAST('42' AS NUMBER) + 1 AS nastepna FROM dual;
-- Access
SELECT CLng('42') + 1 AS nastepna;Każdy przykład daje 43. To nie znaczy, że dowolny błędny napis zachowa się tak samo. SQLite potrafi przekształcić niepoprawny tekst na 0, serwer może zgłosić błąd lub ostrzeżenie zależnie od typu i trybu. SQL Server ma TRY_CAST zwracające NULL dla wielu nieudanych konwersji. Nie używaj SQLite do sprawdzania ścisłej walidacji typów obcego silnika. Liczby z przecinkiem dziesiętnym i daty w formatach regionalnych wymagają świadomego parsowania.
CASE: wybór wartości według warunku
SELECT nazwa, cena,
CASE
WHEN cena < 50 THEN 'tani'
WHEN cena < 200 THEN 'sredni'
ELSE 'drogi'
END AS przedzial
FROM produkty ORDER BY id;CASE wybiera pierwszą pasującą gałąź. Dla naszych produktów otrzymasz sredni, sredni, drogi, tani. Kolejność warunków ma znaczenie: gdyby najpierw było cena < 200, Kabel nie dotarłby do gałęzi cena < 50. Bez ELSE brak dopasowania daje NULL. Wszystkie zwracane wartości powinny mieć zgodny sens i typ.
Taką postać CASE obsługują MySQL, SQL Server, Oracle i SQLite. W Access można zapisać IIf(cena < 50, 'tani', IIf(cena < 200, 'sredni', 'drogi')). IIf w Access ocenia oba wyrażenia wynikowe, więc nie jest uniwersalną osłoną przed dzieleniem przez zero. CASE jest wyrażeniem zwracającym wartość, nie instrukcją sterującą wykonaniem całego programu.
COALESCE i pokrewne funkcje
-- MySQL / SQL Server / Oracle / SQLite
SELECT imie, COALESCE(miasto, 'nie podano') AS miejscowosc
FROM klienci ORDER BY id;Ewa otrzyma „nie podano”. COALESCE bierze pierwszą wartość inną niż NULL. Odpowiedniki dla dwóch argumentów: MySQL IFNULL, SQL Server ISNULL, Oracle NVL, Access Nz. Nie są identyczne w zakresie ustalania typu wyniku, długości tekstu czy konwersji. W Access zapisuj jawnie Nz(miasto, 'nie podano'). Pusty napis nie jest NULL w MySQL, SQL Server i SQLite; Oracle 19c traktuje pusty napis jako NULL. NULLIF(a,b) z poprzedniej lekcji robi inny krok: tworzy NULL, gdy wartości są równe.
Ćwiczenia
- W SQLite wyświetl zamówienia z terminem 14 dni po data.
- Przypisz produktom etykietę „od 100” lub „ponizej 100”.
- Pokaż e-mail klienta, a przy jego braku napis „brak email”. Dlaczego COALESCE(email, ”) nie zawsze jest dobrym rozwiązaniem?
Rozwiązania
SELECT id, DATE(data, '+14 days') AS termin FROM zamowienia ORDER BY id;
SELECT nazwa, CASE WHEN cena >= 100 THEN 'od 100'
ELSE 'ponizej 100' END AS grupa FROM produkty ORDER BY id;
SELECT imie, COALESCE(email, 'brak email') AS kontakt FROM klienci ORDER BY id;Terminy: 24 i 25 stycznia, 15 i 17 lutego 2026. Etykietę „od 100” dostają Klawiatura i Monitor. Brak e-maila dotyczy Jana i Adama. Pusty napis zaciera różnicę między brakiem informacji a istniejącym pustym polem, a w Oracle i tak jest NULL.
Źródła: MySQL — daty, SQL Server DATEDIFF, Oracle — funkcje, Access — funkcje dat, SQLite — daty. INF.03.4: przetwarzanie danych. Dalej: funkcje agregujące.

