Ce face gen_random_uuid() și GENERATED AS IDENTITY
Pentru cheile primare numerice auto-incrementate, PostgreSQL 10+ recomandă sintaxa standard SQL GENERATED ALWAYS AS IDENTITY (sau GENERATED BY DEFAULT AS IDENTITY) în locul vechiului pseudo-tip SERIAL / BIGSERIAL. Coloanele IDENTITY gestionează automat permisiunile secvenței subiacente și previn inserarea accidentală de ID-uri manuale.
Pentru identificatori expuși în URL-uri sau generați în sisteme distribuite, tipul nativ uuid (stocat eficient pe 16 octeți binari, nu ca 36 de caractere text!) împreună cu funcția încorporată gen_random_uuid() (disponibilă în nucleul PostgreSQL 13+ fără extensii externe) generează UUID-uri criptografice versiunea 4.
Clauze, operatori și argumente
| Clauză / Operator | Descriere |
|---|---|
GENERATED ALWAYS AS IDENTITY |
Generează automat valoarea dintr-o secvență și respinge orice INSERT care încearcă să specifice manual o valoare (cu excepția OVERRIDING SYSTEM VALUE). |
GENERATED BY DEFAULT AS IDENTITY |
Generează automat valoarea doar dacă nu a fost furnizată explicit în comanda INSERT. |
uuid |
Tip de date nativ de 128 de biți (16 octeți) pentru stocarea eficientă a identificatorilor UUID. |
gen_random_uuid() |
Funcție încorporată (PostgreSQL 13+) care returnează un UUID v4 aleatoriu securizat criptografic. |
BIGSERIAL / SERIAL |
Sintaxă tradițională PostgreSQL pentru auto-increment; pentru tabele noi se preferă bigint GENERATED ALWAYS AS IDENTITY. |
Exemple
Exemplul 1: Crearea unui tabel cu cheie internă IDENTITY și cheie publică UUID
Combinăm o cheie primară compactă bigint pentru joncțiuni rapide cu un uuid expus în API-ul extern.
CREATE TABLE plati (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
cod_public uuid NOT NULL DEFAULT gen_random_uuid() UNIQUE,
suma_lei numeric(12, 2) NOT NULL CHECK (suma_lei > 0),
creat_la timestamptz NOT NULL DEFAULT NOW()
);
INSERT INTO plati (suma_lei)
VALUES (249.99), (89.50)
RETURNING id, cod_public, suma_lei;
Rezultat interogare
id | cod_public | suma_lei
----+--------------------------------------+----------
1 | f47ac10b-58cc-4372-a567-0e02b2c3d479 | 249.99
2 | 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d | 89.50
(2 rows)
INSERT 0 2
Exemplul 2: Inserarea unui ID explicit cu OVERRIDING SYSTEM VALUE și sincronizarea secvenței
În timpul unei migrări, forțăm un ID specific pe o coloană GENERATED ALWAYS și apoi aliniem secvența la valoarea maximă.
INSERT INTO plati (id, suma_lei)
OVERRIDING SYSTEM VALUE
VALUES (100, 500.00)
RETURNING id, cod_public, suma_lei;
SELECT setval(pg_get_serial_sequence('plati', 'id'), MAX(id)) FROM plati;
Rezultat interogare
id | cod_public | suma_lei
-----+--------------------------------------+----------
100 | 3d6f8a21-7c90-4e1a-8b12-9012abcdef34 | 500.00
(1 row)
setval
--------
100
(1 row)
Greșeli frecvente
- Stocarea UUID-urilor în coloane
VARCHAR(36)sauTEXT: ocupă mai mult decât dublu pe disc și în indecși față de tipul nativuuid(16 octeți) și nu validează automat formatul. - Folosirea tipului
integer(4 octeți, maxim ~2,14 miliarde) în loc debigintpentru tabele cu creștere rapidă: schimbarea tipului unei chei primare pe un tabel de sute de milioane de rânduri necesită rescrierea completă a tabelului.
Comenzi și funcții înrudite
INSERT INTO ... RETURNING: Inserează unul sau mai multe rânduri și returnează imediat valorile generate (ID-uri, timestamp-uri) fără o interogare suplimentară.ON CONFLICT DO UPDATE (UPSERT): Rezolvă atomic conflictele de cheie unică la inserare: ignoră rândul duplicat sau îl actualizează pe loc.CREATE INDEX (B-Tree, GIN, Partial, CONCURRENTLY): Creează indecși B-Tree, GIN (pentru JSONB și Array), indecși parțiali (WHERE) și indecși pe expresii fără blocarea scrierilor.