Das Thema ist nicht neu, aber bei der Gestaltung komplexerer SQL-Logik immer wieder von Interesse: wie generiere ich effizient eine größere Menge von Datensätzen mit einer eindeutigen id? Dazu hat Natalka Roshak eine kleine Serie gestartet, die bislang zwei Artikel umfasst, und in der zunächst vier verschiedene Verfahren vorgestellt werden:
-- rekursive Variante mit connect by level
select level id
from dual
connect by level <= 10;
-- rekursive Variante mit subquery factoring
with
generator (id) as (
select 1 as id from dual
union all
select id + 1
from generator
where id < 10
)
select id
from generator;
-- XML table
select column_value as id
from xmltable ('1 to 10');
-- group by cube
select rownum id
from (select 1
from dual
group by cube( 1, 1, 1, 1)
)
where rownum <= 10;
Mir persönlich war die group by cube Variante unbekannt, aber sie ist auch nicht unbedingt etwas, das man sich merken müsste, da ihre Performance erbärmlich ist. Nicht viel besser schneidet die XML table Lösung ab, so dass man letztlich doch bei den klassischen Varianten bleiben kann - meine erste Wahl ist dabei das kompakte connect by level Verfahren.
Alternativ könnte man noch über ein paar Varianten nachdenken, die Adrian Billington vor einigen Jahren beschrieben hat:
- Verwendung einer pipelined table function
- Verwendung der model clause
Beide Varianten sind offenbar recht flott, aber auch das bringt mich nicht von connect by level ab, dessen einzigen (mir bekannten) größeren Nachteil Tanel Poder gelegentlich erwähnt hat: seine Memory-Nutzung wächst aufgrund des rekursiven Verfahrens mit der Anzahl der generierten Sätze. Daher kann es sinnvoll sein, die Generierung mit mehreren Subqueries (oder CTEs) durchzuführen, die man dann via Cross-Join verbindet.
Kann es sein, das bei den ersten beiden 3 Beispielen die Formatierung etwas durcheinander geraten ist?
AntwortenLöschenDanke - keine Ahnung, wie ich das geschafft hatte...
AntwortenLöschenSollte jetzt korrigiert sein.