DBAtlas · Database operations atlas

Return the modified row (RETURNING / OUTPUT)

Oracle

-- Single row: RETURNING ... INTO (PL/SQL bind variable)
UPDATE employee SET salary = salary * 1.1
WHERE id = 5
RETURNING salary INTO :new_salary;

-- Get back the key generated by an INSERT
INSERT INTO employee (name) VALUES ('Ayse')
RETURNING id INTO :new_id;

RETURNING returns the values of rows changed by INSERT/UPDATE/DELETE (e.g. an auto-generated ID) without a separate SELECT. In Oracle, a single row is returned with RETURNING ... INTO a bind variable, and multiple rows with RETURNING ... BULK COLLECT INTO a collection.

PostgreSQL

INSERT INTO employee (name, salary)
VALUES ('Ayse', 15000)
RETURNING id, name;

UPDATE employee SET salary = salary * 1.1
WHERE department = 'IT'
RETURNING id, salary;

PostgreSQL's RETURNING clause is very flexible: it returns any column (including computed expressions) of the rows affected by INSERT, UPDATE, DELETE and MERGE statements directly as a result set. It is the cleanest way to obtain generated serial/identity values.

MySQL

-- MySQL has no RETURNING; the generated key is retrieved separately:
INSERT INTO employee (name, salary) VALUES ('Ayse', 15000);
SELECT LAST_INSERT_ID();

-- MariaDB 10.5+ supports INSERT ... RETURNING:
INSERT INTO employee (name) VALUES ('Ayse') RETURNING id;

MySQL does not support standard RETURNING; the auto-increment key generated by an INSERT is retrieved with LAST_INSERT_ID(), and updated values are read with a separate SELECT. MariaDB offers INSERT ... RETURNING since 10.5 and DELETE ... RETURNING since 10.0.

SQL Server

INSERT INTO employee (name, salary)
OUTPUT INSERTED.id, INSERTED.name
VALUES ('Ayse', 15000);

UPDATE employee SET salary = salary * 1.1
OUTPUT DELETED.salary AS old_salary, INSERTED.salary AS new_salary
WHERE id = 5;

SQL Server's equivalent is the OUTPUT clause: it accesses the INSERTED (new values) and DELETED (old values) pseudo-tables; both can be used in an UPDATE. With OUTPUT ... INTO the results can be written to a table/table variable. Ideal for copying changes into an audit table.

MongoDB

// findOneAndUpdate returns the modified document
db.employee.findOneAndUpdate(
  { id: 5 },
  { $mul: { salary: 1.1 } },
  { returnDocument: "after" }   // return the updated version
)

In MongoDB the findOneAndUpdate / findOneAndDelete / findOneAndReplace commands return the affected document in a single atomic operation. returnDocument: 'before' gives the version before the change, 'after' the version after. insertOne returns the _id of the inserted document.

Redis

# Some commands return the old/new value directly:
SET counter 0 GET       # (6.2+) returns the old value and writes the new one (replaces GETSET)
INCR visits          # increments and returns the new value

Redis has no separate RETURNING, but many write commands return the result directly: INCR/INCRBY return the new value, SET ... GET the old value (GETSET is deprecated since 6.2), and LPOP/RPOP the removed element. For atomic read-write, this behavior substitutes for RETURNING.

Elasticsearch

# The _update response can return the result:
POST employee/_update/5
{
  "script": { "source": "ctx._source.salary *= 1.1" },
  "_source": true
}
# The response returns the updated document in get._source

In Elasticsearch index/update operations return result metadata (_id, _version, result). To get the body of the updated document, add '_source': true to the _update request; the get field of the response contains the current _source. No separate GET call is needed.

Open in DBAtlas →