De WITH
clausule is voor factoring van subquery's, ook bekend als algemene tabeluitdrukkingen of CTE's:
Met de clausule WITH query_name kunt u een naam toewijzen aan een subqueryblok. U kunt vervolgens op meerdere plaatsen in de query naar het subqueryblok verwijzen door query_name op te geven. Oracle Database optimaliseert de query door de naam van de query te behandelen als een inline-weergave of als een tijdelijke tabel.
In je tweede voorbeeld, wat je temp_table
. hebt genoemd is een inline-weergave, geen tijdelijke tabel.
In veel gevallen komt de keuze om te gebruiken neer op uw voorkeursstijl, en CTE's kunnen code leesbaarder maken, met name met meerdere niveaus van subquery's (de meningen variëren natuurlijk). Als u slechts één keer naar de CTE/inline-weergave verwijst, ziet u waarschijnlijk geen verschil in prestaties en kan de optimiser uiteindelijk met hetzelfde plan eindigen.
Ze zijn echter vooral handig wanneer u dezelfde subquery op meer dan één plaats moet gebruiken, zoals in een unie. U kunt een inline-weergave naar een CTE trekken, zodat de code niet wordt herhaald, en de optimiser deze kan realiseren als hij denkt dat dat gunstig zou zijn.
Bijvoorbeeld dit gekunstelde voorbeeld:
select curr from (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr >= 0
union all
select -1 * curr from (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
) temp_table
where curr < 0
kan worden omgevormd tot:
with temp_table as (
select curr from tableone t1
left join tabletwo t2 on (t1.empid = t2.empid)
)
select curr from temp_table
where curr >= 0
union all
select -1 * curr from temp_table
where curr < 0
De subquery hoeft niet meer herhaald te worden. Hoe ingewikkelder de herhaalde code is, hoe voordeliger het is vanuit onderhoudsoogpunt om een CTE te gebruiken. En hoe duurder de subquery, hoe meer prestatievoordeel u zou zien van het gebruik van een CTE, hoewel de optimizer meestal redelijk goed is in het uitzoeken wat je toch doet.