Tipuri de Date Range și Multirange în PostgreSQL (tsrange, daterange) în PostgreSQL

Ghid complet pentru Range Types și Multiranges în PostgreSQL 14+: stocarea intervalelor continue și discontinue, operatori de suprapunere (&&) și prevenirea rezervărilor duble cu constrângeri GiST.

Sintaxă SQL
CREATE TABLE rezervari (camera_id INT, perioada TSRANGE, EXCLUDE USING gist (camera_id WITH =, perioada WITH &&));

Î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ă.

Prevenirea rezervărilor duble cu constrângeri de excludere (EXCLUDE)
-- 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ă true dacă 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!