gen_random_uuid() și GENERATED AS IDENTITY în PostgreSQL

JSONB, Array și tipuri avansate PostgreSQL 13+ (gen_random_uuid nativ; IDENTITY din PG 10+)

Definește chei primare moderne cu coloane auto-incrementate standard SQL (IDENTITY) sau identificatori unici globali (UUID v4).

Sintaxă SQL
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,nid_public uuid DEFAULT gen_random_uuid() NOT NULL UNIQUE

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) sau TEXT: ocupă mai mult decât dublu pe disc și în indecși față de tipul nativ uuid (16 octeți) și nu validează automat formatul.
  • Folosirea tipului integer (4 octeți, maxim ~2,14 miliarde) în loc de bigint pentru 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