sql >> Database teknologi >  >> RDS >> PostgreSQL

Garanterer postgres union udførelsesrækkefølgen, når man påberåber sig funktioner med bivirkninger?

I praksis vil de blive udført i den angivne rækkefølge, men der er ingen garanti.

Hvis det er garanteret, vil det være dækket af dokumentationen eller SQL-standarden. Jeg kan ikke se nogen omtale af rækkefølge for udførelse af en UNION i enten.

Hvis optimeringsværktøjet havde en grund til at udføre den ene før den anden, ville det være gratis at gøre det.

For at sikre udførelsesrækkefølgen, kør sætninger i den ønskede rækkefølge:

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

Hvis du ønsker at reducere rundture, skal du bruge din kundes batchfaciliteter, hvis det er muligt, eller brug en DO blokere:

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

Hvis du har brug for at returnere værdier, skal du bruge en funktion og RETURN QUERY eller RETURN NEXT .

Eller du kan tvinge bestilling med en CTE, fordi i PostgreSQL (desværre) CTE'er fungere som optimeringshegn, der fremtvinger materialisering af resultater . AFAIK PostgreSQL behøver dog stadig ikke at udføre CTE-vilkårene i den rækkefølge, de er skrevet, eller den rækkefølge, de refereres til; den eneste garanti, du får, er, hvis du gør dette:

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

derefter function1 skal udføres og materialiseres først. Det er dog en PostgreSQL-specifik fejlfunktion; det er ikke sandt for andre databasemotorer, ikke garanteret af standarden, og du bør ikke stole på det.

Det strækker sig ikke til

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

... som i dette tilfælde kan PostgreSQL udføre de uafhængige CTE-vilkår i begge rækkefølge.

Igen, med sammenføjninger gælder det samme princip. Hvis vilkårene er uafhængige, kan systemet vælge at køre dem i en hvilken som helst rækkefølge, selvom det generelt ikke gør det. Så:

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

kunne evaluere og materialisere bar() foren derefter resultaterne på foo() .

Hvis du vil have bestilt udførelse, bør du ikke stole på faste operationer som fagforeninger og joinforbindelser. Brug separate forespørgsler eller procedurekode.

Ja, det er der.

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



  1. mysql_fetch_array returnerer kun én række

  2. Indsæt i tabel ved hjælp af array-metoden med overordnet ID

  3. Filnavn i WHERE-sætningen i Mysql returnerer intet

  4. LISTEN/NOTIFY ved hjælp af pg_notify(text, text) i PostgreSQL