NEW
PG 7.4+→ recordIn a row-level trigger, contains the new row for INSERT and UPDATE operations. NULL for DELETE triggers.
Signature
NEW → recordExamples
NEW.updated_at := now();Sets updated_at on the new row before INSERT/UPDATEIF NEW.email IS DISTINCT FROM OLD.email THEN
NEW.email_verified := false;
END IF;Resets verification when email changes-- Auto-set updated_at on every UPDATE
IF TG_OP = 'UPDATE' THEN
NEW.updated_at := now();
END IF;
RETURN NEW;updated_at always reflects the time of the last modification-- Auto-fill search_vector from title + body before INSERT or UPDATE
NEW.search_vector := to_tsvector('english',
coalesce(NEW.title, '') || ' ' || coalesce(NEW.body, ''));
RETURN NEW;Full-text search vector auto-maintained without a separate jobA PL/pgSQL function returns NULL by default if no RETURN statement is reached. In a BEFORE ROW trigger, returning NULL suppresses the INSERT or UPDATE without any error or warning — the operation simply disappears.
✓ Instead: Always end BEFORE ROW trigger functions with `RETURN NEW;` for INSERT/UPDATE, or `RETURN OLD;` for DELETE. Add a guard: `RETURN NEW;` unconditionally after your logic.
In a BEFORE trigger, you can modify `NEW` fields before the row is written to the table. Return `NEW` to proceed with the (possibly modified) row, or return `NULL` to suppress the operation entirely.
NEW.search_vector := to_tsvector('english', coalesce(NEW.title,'') || ' ' || coalesce(NEW.body,''));
RETURN NEW;Auto-updates search_vector before INSERT/UPDATE