sql >> Databasteknik >  >> RDS >> PostgreSQL

Garanterar postgres union utförandeordning när man åberopar funktioner med biverkningar?

I praktiken kommer de att utföras i den ordning som ges, men det finns ingen garanti.

Om det är garanterat kommer det att täckas i dokumentationen eller SQL-standarden. Jag ser inget omnämnande av ordningsföljd för en UNION i antingen.

Om optimeraren hade en anledning att köra den ena före den andra skulle det vara gratis att göra det.

För att säkerställa körningsordning, kör programsatser i önskad ordning:

SELECT * FROM func1();
SELECT * FROM func2();

Om du vill minska tur-och-retur-resor, använd om möjligt din kunds batchfaciliteter, eller använd en DO blockera:

DO
$$
BEGIN
  PERFORM proc1();
  PERFORM proc2();
END;
$$;

Om du behöver returnera värden, använd en funktion och RETURN QUERY eller RETURN NEXT .

Eller så kan du tvinga beställning med en CTE, eftersom i PostgreSQL (tyvärr) CTEs fungera som optimeringsstängsel som tvingar fram materialisering av resultat . AFAIK PostgreSQL behöver dock fortfarande inte exekvera CTE-villkoren i den ordning de skrivs, eller den ordning de refereras till; den enda garantin du får är om du gör detta:

WITH f1 AS (SELECT * FROM function1())
SELECT * FROM function2()
UNION ALL
SELECT * FROM f1;

sedan function1 måste utföras och materialiseras först. Det är dock en PostgreSQL-specifik felfunktion; det är inte sant för andra databasmotorer, inte garanterat av standarden, och du bör inte lita på det.

Det sträcker sig inte till

WITH f1 AS (SELECT * FROM function1())
     f2 AS (SELECT * FROM function2())
SELECT * FROM f2
UNION ALL
SELECT * FROM f1;

... som i det här fallet kan PostgreSQL exekvera de oberoende CTE-termerna i vilken ordning som helst.

Återigen, med sammanfogningar gäller samma princip. Om termer är oberoende kan systemet välja att köra dem i valfri ordning, även om det i allmänhet inte gör det. Så:

select null::void from (select 1 from foo() ) left join (select 1 from bar()) on true

skulle kunna utvärdera och materialisera bar() slå sedan samman dess resultat på foo() .

Om du vill ha beordrad utförande bör du inte förlita dig på fastställda operationer som fackföreningar och sammanslutningar. Använd separata frågor eller procedurkod.

Ja, det finns det.

SELECT * FROM function1();
SELECT * FROM function2();



  1. Fix "ERROR 1250 (42000):Tabell '...' från en av SELECT:erna kan inte användas i ORDER-satsen" i MariaDB

  2. Oracle till PostgreSQL — Markörer och vanliga tabelluttryck

  3. Spara array i databasen eller skapa olika kolumner

  4. MySQL-fråga för att dra objekt, men alltid visa en viss överst