Introdusă în PostgreSQL 15 și îmbunătățită în versiunile 16 și 17 (cu suport complet pentru RETURNING), comanda standard SQL MERGE INTO permite efectuarea condiționată de operațiuni INSERT, UPDATE și DELETE asupra unui tabel țintă pe baza rezultatului alăturării cu un tabel sursă, totul într-o singură instrucțiune SQL atomică.
Sincronizarea stocului de produse folosind MERGE
-- 1. Tabelul principal de stocuri
CREATE TABLE stocuri (
produs_id INT PRIMARY KEY,
cantitate INT NOT NULL,
ultima_actualizare TIMESTAMPTZ DEFAULT NOW()
);
-- 2. Tabelul temporar de recepție marfă (date noi sosite de la furnizor)
CREATE TABLE receptie_marfa (
produs_id INT PRIMARY KEY,
cantitate_noua INT NOT NULL
);
-- 3. Sincronizăm ambele tabele printr-o singură comandă MERGE:
MERGE INTO stocuri s
USING receptie_marfa r
ON s.produs_id = r.produs_id
-- Dacă produsul există deja în stoc -> adăugăm cantitatea primită:
WHEN MATCHED AND (s.cantitate + r.cantitate_noua) > 0 THEN
UPDATE SET
cantitate = s.cantitate + r.cantitate_noua,
ultima_actualizare = NOW()
-- Dacă noua cantitate ar deveni 0 sau negativă -> eliminăm produsul:
WHEN MATCHED AND (s.cantitate + r.cantitate_noua) <= 0 THEN
DELETE
-- Dacă produsul este complet nou -> îl inserăm în stoc:
WHEN NOT MATCHED THEN
INSERT (produs_id, cantitate, ultima_actualizare)
VALUES (r.produs_id, r.cantitate_noua, NOW());
MERGE vs. INSERT … ON CONFLICT (UPSERT)
Deși ambele comenzi pot implementa operațiuni de tip „Upsert”, ele au arhitecturi și scopuri diferite:
| Caracteristică | MERGE INTO | INSERT … ON CONFLICT DO UPDATE |
|---|---|---|
| Standard SQL | Complet conform cu standardul ANSI SQL:2008. | Extensie specifică PostgreSQL (și SQLite). |
| Acțiuni Suportate | INSERT, UPDATE, DELETE combinate liber în funcție de condiții multiple. |
Doar INSERT sau UPDATE (nu poate efectua DELETE direct). |
| Tratarea Concurenței Ridicate | Poate arunca eroare de serializare la scrieri concurente masive pe același rând. | Garantat atomic împotriva condițiilor de concurență (race conditions) la nivel de rând. |
| Caz Recomandat | Proceduri batch de noapte, procese ETL, sincronizări de tabele întregi dintr-un staging. | Interogări OLTP ultra-rapide la nivel de rând unic (ex: salvare sesiune utilizator). |
Noutate PostgreSQL 17: Clauza RETURNING în MERGE
-- În PostgreSQL 17+, MERGE suportă clauza RETURNING cu funcția merge_action():
MERGE INTO stocuri s
USING receptie_marfa r ON s.produs_id = r.produs_id
WHEN MATCHED THEN UPDATE SET cantitate = s.cantitate + r.cantitate_noua
WHEN NOT MATCHED THEN INSERT (produs_id, cantitate) VALUES (r.produs_id, r.cantitate_noua)
RETURNING merge_action(), s.produs_id, s.cantitate;
-- Returnează exact acțiunea întreprinsă per rând: 'UPDATE' sau 'INSERT'!