Основен отговор
Има CTE (Общи таблични изрази) в Postgres (като във всяка голяма модерна RDBMS с изключение на MySQL). От версия 9.1, която включва CTE за модифициране на данни. Те могат да бъдат „вложени“.
Актуализация:MySQL 8.0 най-накрая добавя CTE.
За разлика от подзаявките CTE представляват бариери за оптимизация. Инструментът за планиране на заявки не може да вмъква тривиални команди в основната команда или да пренарежда обединяванията между основната заявка и CTE. Същото е възможно и с подзаявки. Може да е (много) добро или (много) лошо за производителността, зависи.
И в двата случая CTE изискват малко повече разходи (разходи за производителност) от подзаявките.
Актуализация:Postgres 12 най-накрая може да вгради обикновени CTEs в основната заявка.
Подробности, които не сте поискали
Въпросът ви е много елементарен, горното вероятно е достатъчно за отговор. Но ще добавя малко за напреднали потребители (и пример за код, за да покажа синтаксиса).
Всички CTE на заявка се базират на една и съща моментна снимка на базата данни. Следващият CTE може да използва повторно изхода на предишни CTE (вътрешни временни таблици), но ефектите върху основните таблици са невидими за други CTE. Последователността от множество CTE е произволна освен нещо се връща с RETURNING
клауза за INSERT
, UPDATE
, DELETE
- без значение за SELECT
, тъй като не променя нищо и просто чете от моментната снимка.
Това може да има фини ефекти с множество актуализации, които биха засегнали един и същ ред. Само един актуализацията може да засегне всеки ред. Кой от тях се влияе от последователността на CTEs.
Опитайте се да предвидите резултата:
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 Fiddle
Не се разочаровайте, съмнявам се, че тук има много хора, които биха могли да го направят. :)
Същината на това:избягвайте конфликтни команди в CTEs.