DBAtlas · データベース運用アトラス

変更された行を返す(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 は、INSERT/UPDATE/DELETE で変更された行の値(例: 自動生成された ID)を別の SELECT なしで返す。Oracle では、単一行は RETURNING ... INTO でバインド変数に、複数行は RETURNING ... BULK COLLECT INTO でコレクションに返す。

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 の RETURNING 句は非常に柔軟で、INSERT、UPDATE、DELETE、MERGE 文の影響を受けた行の任意の列(計算式を含む)を結果セットとして直接返す。生成された serial/identity の値を取得する最もすっきりした方法。

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 は標準の RETURNING をサポートしない。INSERT で生成された自動採番キーは LAST_INSERT_ID() で取得し、更新された値は別の SELECT で読み取る。MariaDB は 10.5 以降で INSERT ... RETURNING を、10.0 以降で DELETE ... RETURNING を提供する。

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 で相当するのは OUTPUT 句で、INSERTED(新しい値)と DELETED(古い値)の疑似テーブルにアクセスする。UPDATE では両方を使用できる。OUTPUT ... INTO で結果をテーブル/テーブル変数に書き込める。変更を監査テーブルにコピーするのに最適。

MongoDB

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

MongoDB では findOneAndUpdate / findOneAndDelete / findOneAndReplace コマンドが、影響を受けたドキュメントを単一のアトミックな操作で返す。returnDocument: 'before' は変更前の版を、'after' は変更後の版を返す。insertOne は挿入したドキュメントの _id を返す。

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 には独立した RETURNING はないが、多くの書き込みコマンドは結果を直接返す: INCR/INCRBY は新しい値を、SET ... GET は古い値を(GETSET は 6.2 以降非推奨)、LPOP/RPOP は取り出した要素を返す。アトミックな読み書きでは、この挙動が 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

Elasticsearch では、index/update 操作は結果のメタデータ(_id、_version、result)を返す。更新されたドキュメントの本体を取得するには、_update リクエストに '_source': true を追加する。レスポンスの get フィールドに現在の _source が含まれる。別の GET 呼び出しは不要。

DBAtlas で開く →