În bazele de date clasice, gestionarea unui interval (cum ar fi o perioadă de valabilitate sau o rezervare hotelieră) necesită două coloane separate: data_inceput și data_sfarsit. Verificarea dacă două intervale se suprapun necesită condiții SQL lungi și predispuse la erori (start_a <= end_b AND end_a >= start_b). Range Types și Multiranges (PostgreSQL 14+) tratează intervalul ca pe un tip de dată atomic de primă clasă.
-- Activăm extensia btree_gist pentru a putea combina egalitatea cu suprapunerea de intervale
CREATE EXTENSION IF NOT EXISTS btree_gist;
-- Tabel de rezervări hoteliere:
CREATE TABLE rezervari_camere (
id SERIAL PRIMARY KEY,
camera_id INT NOT NULL,
perioada DATERANGE NOT NULL,
-- Constrângerea garantează la nivel hardware că o cameră NU poate avea rezervări suprapuse!
CONSTRAINT fara_suprapunere EXCLUDE USING gist (
camera_id WITH =,
perioada WITH &&
)
);
-- Inserăm prima rezervare: 1-10 Octombrie 2026:
INSERT INTO rezervari_camere (camera_id, perioada)
VALUES (101, daterange('2026-10-01', '2026-10-10', '[)')); -- '[' = inclus, ')' = exclus
-- O a doua rezervare care se suprapune (5-12 Octombrie) este respinsă AUTOMAT cu eroare:
INSERT INTO rezervari_camere (camera_id, perioada)
VALUES (101, daterange('2026-10-05', '2026-10-12', '[)'));
-- ERROR: conflicting key value violates exclusion constraint "fara_suprapunere"
Tipurile de Date Range Native
| Tip de Dată | Descriere | Tip Multirange (Postgres 14+) |
|---|---|---|
daterange |
Interval de date calendaristice (fără componentă orară). | datemultirange |
tsrange |
Interval de timestamp-uri fără fus orar. | tsmultirange |
tstzrange |
Interval de timestamp-uri cu fus orar (recomandat în sisteme globale). | tstzmultirange |
numrange |
Interval de numere zecimale continue (ex: trepte de salarizare). | nummultirange |
int4range / int8range |
Interval de numere întregi discrete. | int4multirange / int8multirange |
Operatori Esențiali pe Intervale
perioada_a && perioada_b→ Suprapunere (Overlaps): Returneazătruedacă cele două intervale au cel puțin un punct comun.perioada @> valoare→ Conține (Contains): Verifică dacă o dată specifică se află în interiorul intervalului.valoare <@ perioada→ Conținut în (Contained by): Inversul operatorului@>.perioada_a * perioada_b→ Intersecție: Returnează intervalul comun rezultat din cele două intervale.
Noutatea PostgreSQL 14: Tipul Multirange
Un Multirange reprezintă o colecție ordonată de intervale disjuncte (cu goluri între ele). De exemplu, programul unui medic care lucrează între 08:00-12:00 și 14:00-18:00 poate fi stocat într-o singură valoare atomică:
SELECT tsmultirange(
tsrange('2026-10-24 08:00', '2026-10-24 12:00'),
tsrange('2026-10-24 14:00', '2026-10-24 18:00')
) @> '2026-10-24 10:30'::TIMESTAMP; -- Returnează TRUE!