PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Заявките за тип SELECT ли са единственият тип, който може да бъде вложен?

Основен отговор

Има 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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Не е намерен подходящ драйвер при включването на необходимите драйвери с maven-assembly-plugin

  2. LIKE заявка за елементи от плосък jsonb масив

  3. Мигриране на PostgreSQL към облака – Сравняване на решения от Amazon, Google и Microsoft

  4. Граници на думите на PostgreSQL Regex?

  5. Как make_interval() работи в PostgreSQL