基本的な答え
CTEがあります (一般的なテーブル式) Postgres (MySQLを除くすべての主要な最新のRDBMSと同様)。データ変更CTEを含むバージョン9.1以降。それらは「ネスト」することができます。
更新:MySQL8.0はついにCTEを追加します。
サブクエリとは異なり CTEは最適化の障壁となります。クエリプランナーは、些細なコマンドをメインコマンドにインライン化したり、メインクエリとCTE間の結合を並べ替えたりすることはできません。サブクエリでも同じことが可能です。パフォーマンスに(非常に)良い場合と(非常に)悪い場合があります。
いずれの場合も、CTEはサブクエリよりも少し多くのオーバーヘッド(パフォーマンスコスト)を必要とします。
更新:Postgres12は最終的にプレーンCTEをインライン化できますメインクエリで。
あなたが求めなかった詳細
あなたの質問は非常に基本的です、上記はおそらく答えるのに十分です。ただし、上級ユーザー向けに少し追加します(および構文を示すコード例)。
クエリのすべてのCTEは、同じスナップショットに基づいています。 データベースの。次のCTEは出力を再利用できます 以前のCTE(内部一時テーブル)の場合ですが、基になるテーブルへの影響は他のCTEでは見えません。複数のCTEのシーケンスは、を除いて任意です。 RETURNING
で何かが返されます INSERT
の句 、UPDATE
、DELETE
-SELECT
には関係ありません 、何も変更せず、スナップショットから読み取るだけなので。
これは、同じ行に影響を与える複数の更新で微妙な影響を与える可能性があります。 1つのみ 更新は各行に影響を与える可能性があります。どちらがCTEのシーケンスに影響されます。
結果を予測してみてください:
CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');
WITH sel AS (SELECT * FROM t)
, up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
, up2 AS (UPDATE t SET txt = t.txt || '2'
FROM up1
WHERE up1.t_id = t.t_id
RETURNING t.*)
, ins AS (INSERT INTO t VALUES (4, 'bamm'))
, up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't' AS source, * FROM t;
SQLフィドル
がっかりしないでください、私はそれをすることができたかもしれない多くがここにいるのではないかと思います。 :)
この要点:避ける CTEで競合するコマンド。