INSERT INTO … RETURNING în PostgreSQL

Modificare date și tranzacții PostgreSQL 8.2+ (standard în PostgreSQL 15–17)

Inserează unul sau mai multe rânduri și returnează imediat valorile generate (ID-uri, timestamp-uri) fără o interogare suplimentară.

Sintaxă SQL
INSERT INTO tabel (col1, col2) VALUES (val1, val2) [, ...] RETURNING id, col1, creat_la;

Ce face INSERT INTO ... RETURNING

Comanda INSERT INTO adaugă rânduri noi într-un tabel, fie din valori explicite (VALUES), fie din rezultatul unei interogări (INSERT INTO ... SELECT). În PostgreSQL, clauza RETURNING atașată la finalul unui INSERT (dar și la UPDATE sau DELETE) returnează imediat coloanele dorite din rândurile nou create.

Aceasta elimină complet nevoia apelurilor suplimentare de tip LAST_INSERT_ID() și funcționează impecabil și atunci când inserăm zeci de rânduri într-o singură instrucțiune multi-row VALUES.

Clauze, operatori și argumente

Clauză / Operator Descriere
INSERT INTO tabel (coloane) Specifică tabelul țintă și lista explicită de coloane care primesc valori.
VALUES (...), (...) Furnizează unul sau mai multe tupluri de valori pentru inserare într-o singură comandă atomică.
DEFAULT Cuvânt cheie folosit în VALUES pentru a aplica valoarea implicită a coloanei respective.
RETURNING * / expr Returnează rândurile inserate (inclusiv ID-urile generate de secvențe/UUID și valorile DEFAULT) exact ca un SELECT.

Exemple

Exemplul 1: Inserarea mai multor produse și preluarea ID-urilor cu RETURNING

Inserăm două produse dintr-un foc și cerem înapoi id-ul autogenerat, sku-ul și momentul creării.

INSERT INTO produse (sku, denumire, pret)
VALUES
    ('MON-27-4K', 'Monitor IPS 27 inch 4K', 1699.90),
    ('KBD-MECH-RO', 'Tastatură Mecanică Layout RO', 429.00)
RETURNING id, sku, pret, creat_la;

Rezultat interogare

 id |     sku     |  pret   |          creat_la          
----+-------------+---------+----------------------------
 41 | MON-27-4K   | 1699.90 | 2025-03-20 10:14:22.418+02
 42 | KBD-MECH-RO |  429.00 | 2025-03-20 10:14:22.418+02
(2 rows)

INSERT 0 2

Exemplul 2: Arhivarea și copierea rândurilor cu INSERT INTO … SELECT … RETURNING

Copiem comenzile finalizate din 2024 într-un tabel de arhivă și afișăm ID-urile procesate.

INSERT INTO arhiva_comenzi (comanda_id, client_id, total_lei, plasata_la)
SELECT id, client_id, total_lei, plasata_la
FROM comenzi
WHERE plasata_la < '2025-01-01' AND status = 'livrata'
RETURNING comanda_id, total_lei;

Rezultat interogare

 comanda_id | total_lei 
------------+-----------
       1012 |    340.00
       1019 |    890.50
(2 rows)

INSERT 0 2

Greșeli frecvente

  • Omiterea listei de coloane în INSERT INTO tabel VALUES (...): dacă ordinea coloanelor se schimbă sau se adaugă o coloană nouă în tabel, interogarea va eșua sau va insera date în coloana greșită.
  • Executarea unui SELECT MAX(id) după INSERT pentru a afla cheia generată: într-o aplicație concurentă, o altă sesiune poate insera un rând între timp; folosește întotdeauna RETURNING id.

Comenzi și funcții înrudite